Compare commits
11 Commits
v1
...
logging_10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9394b13b25 | ||
|
|
b0ffab807c | ||
|
|
d9a2c8dc60 | ||
|
|
44a53b1fd4 | ||
|
|
c9926fb13a | ||
|
|
ca390d2c10 | ||
|
|
83692e17fd | ||
|
|
65a7fd023e | ||
|
|
ac89b148a4 | ||
|
|
b41ca12451 | ||
|
|
311567599e |
621
mozilla/htmlparser/src/nsAVLTree.cpp
Normal file
621
mozilla/htmlparser/src/nsAVLTree.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
78
mozilla/htmlparser/src/nsAVLTree.h
Normal file
78
mozilla/htmlparser/src/nsAVLTree.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#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___ */
|
||||
|
||||
124
mozilla/modules/libreg/xpcom/nsIRegistry.idl
Normal file
124
mozilla/modules/libreg/xpcom/nsIRegistry.idl
Normal file
@@ -0,0 +1,124 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*
|
||||
* The Initial Developer of this code under the MPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIEnumerator.idl"
|
||||
|
||||
typedef PRUint32 nsRegistryKey;
|
||||
typedef long nsWellKnownRegistry;
|
||||
|
||||
[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
|
||||
interface nsIRegistry : nsISupports
|
||||
{
|
||||
const long None = 0;
|
||||
const long Users = 1;
|
||||
const long Common = 2;
|
||||
const long CurrentUser = 3;
|
||||
|
||||
const long ApplicationComponentRegistry = 1;
|
||||
const long ApplicationRegistry = 2;
|
||||
|
||||
// Dont use this one. This for internal use only.
|
||||
const long ApplicationCustomRegistry = -1;
|
||||
|
||||
void open(in string regFile);
|
||||
void openWellKnownRegistry(in nsWellKnownRegistry regid);
|
||||
|
||||
void flush();
|
||||
boolean isOpen();
|
||||
|
||||
nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
|
||||
nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
|
||||
void removeKey(in nsRegistryKey baseKey, in wstring keyname);
|
||||
|
||||
wstring getString(in nsRegistryKey baseKey, in wstring valname);
|
||||
void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
|
||||
|
||||
string getStringUTF8(in nsRegistryKey baseKey, in string path);
|
||||
void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
|
||||
|
||||
void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
|
||||
void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
|
||||
PRInt32 getInt(in nsRegistryKey baseKey, in string path);
|
||||
void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
|
||||
PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
|
||||
void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
|
||||
|
||||
/**
|
||||
* addSubtree() and friends need to be renamed to addKeyUTF8().
|
||||
* If you are using these forms make sure you pass UTF8 data
|
||||
*/
|
||||
nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
|
||||
void removeSubtree(in nsRegistryKey baseKey, in string path);
|
||||
nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
|
||||
|
||||
nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
|
||||
void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
|
||||
nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
|
||||
|
||||
nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
|
||||
nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
|
||||
nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
|
||||
|
||||
const unsigned long String = 1;
|
||||
const unsigned long Int32 = 2;
|
||||
const unsigned long Bytes = 3;
|
||||
const unsigned long File = 4;
|
||||
|
||||
unsigned long getValueType(in nsRegistryKey baseKey, in string path);
|
||||
PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
|
||||
void deleteValue(in nsRegistryKey baseKey, in string path);
|
||||
|
||||
/**
|
||||
* escapeKey() takes arbitrary binary data and converts it into
|
||||
* valid ASCII which can be used as registry key or value names
|
||||
*/
|
||||
void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
|
||||
void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
|
||||
|
||||
attribute string currentUserName;
|
||||
|
||||
void pack();
|
||||
};
|
||||
|
||||
[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
|
||||
interface nsIRegistryEnumerator : nsIEnumerator
|
||||
{
|
||||
void currentItemInPlaceUTF8(out nsRegistryKey key,
|
||||
[shared, retval] out string item);
|
||||
};
|
||||
|
||||
[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
|
||||
interface nsIRegistryNode : nsISupports
|
||||
{
|
||||
readonly attribute string nameUTF8;
|
||||
readonly attribute wstring name;
|
||||
readonly attribute nsRegistryKey key;
|
||||
};
|
||||
|
||||
[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
|
||||
interface nsIRegistryValue : nsISupports
|
||||
{
|
||||
readonly attribute wstring name;
|
||||
readonly attribute string nameUTF8;
|
||||
readonly attribute unsigned long type;
|
||||
readonly attribute PRUint32 length;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#include "nsIRegistryUtils.h"
|
||||
%}
|
||||
44
mozilla/modules/libreg/xpcom/nsIRegistryUtils.h
Normal file
44
mozilla/modules/libreg/xpcom/nsIRegistryUtils.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*- 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.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#ifndef __nsIRegistryUtils_h
|
||||
#define __nsIRegistryUtils_h
|
||||
|
||||
#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
|
||||
#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
|
||||
/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
|
||||
#define NS_REGISTRY_CID \
|
||||
{ 0xbe761f00, 0xa3b0, 0x11d2, \
|
||||
{0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} }
|
||||
|
||||
/*------------------------------- Error Codes ----------------------------------
|
||||
------------------------------------------------------------------------------*/
|
||||
#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
|
||||
#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
|
||||
#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
|
||||
#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
|
||||
#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
|
||||
#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
|
||||
#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
|
||||
#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
|
||||
#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
|
||||
|
||||
#endif
|
||||
1998
mozilla/modules/libreg/xpcom/nsRegistry.cpp
Normal file
1998
mozilla/modules/libreg/xpcom/nsRegistry.cpp
Normal file
File diff suppressed because it is too large
Load Diff
55
mozilla/modules/libreg/xpcom/nsRegistry.h
Normal file
55
mozilla/modules/libreg/xpcom/nsRegistry.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* -*- 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.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Kandrot <kandrot@netscape.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef nsRegistry_h__
|
||||
#define nsRegistry_h__
|
||||
|
||||
#include "nsIRegistry.h"
|
||||
#include "NSReg.h"
|
||||
|
||||
struct nsRegistry : public nsIRegistry {
|
||||
// This class implements the nsISupports interface functions.
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// This class implements the nsIRegistry interface functions.
|
||||
NS_DECL_NSIREGISTRY
|
||||
|
||||
// ctor/dtor
|
||||
nsRegistry();
|
||||
virtual ~nsRegistry();
|
||||
|
||||
int SetBufferSize( int bufsize ); // changes the file buffer size for this registry
|
||||
|
||||
protected:
|
||||
HREG mReg; // Registry handle.
|
||||
#ifdef EXTRA_THREADSAFE
|
||||
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
|
||||
#endif
|
||||
char *mCurRegFile; // these are to prevent open from opening the registry again
|
||||
nsWellKnownRegistry mCurRegID;
|
||||
|
||||
NS_IMETHOD Close();
|
||||
}; // nsRegistry
|
||||
|
||||
#endif
|
||||
621
mozilla/parser/htmlparser/src/nsAVLTree.cpp
Normal file
621
mozilla/parser/htmlparser/src/nsAVLTree.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
78
mozilla/parser/htmlparser/src/nsAVLTree.h
Normal file
78
mozilla/parser/htmlparser/src/nsAVLTree.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#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___ */
|
||||
|
||||
923
mozilla/string/obsolete/nsStr.cpp
Normal file
923
mozilla/string/obsolete/nsStr.cpp
Normal file
@@ -0,0 +1,923 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Original Author:
|
||||
* Rick Gessner <rickg@netscape.com>
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*/
|
||||
|
||||
/******************************************************************************************
|
||||
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};
|
||||
static PRBool gStringAcquiredMemory = PR_TRUE;
|
||||
|
||||
/**
|
||||
* This method initializes all the members of the nsStr structure
|
||||
*
|
||||
* @update gess10/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
|
||||
aDest.mStr=(char*)gCommonEmptyBuffer;
|
||||
aDest.mLength=0;
|
||||
aDest.mCapacity=0;
|
||||
aDest.mCharSize=aCharSize;
|
||||
aDest.mOwnsBuffer=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes all the members of the nsStr structure
|
||||
* @update gess10/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
|
||||
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
|
||||
aDest.mLength=aLength;
|
||||
aDest.mCapacity=aCapacity;
|
||||
aDest.mCharSize=aCharSize;
|
||||
aDest.mOwnsBuffer=aOwnsBuffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
|
||||
* @update gess10/30/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsStr::Destroy(nsStr& aDest) {
|
||||
if((aDest.mStr) && (aDest.mStr!=(char*)gCommonEmptyBuffer)) {
|
||||
Free(aDest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
* to grow to a given size. The original contents are not preserved.
|
||||
* @update gess 3/30/98
|
||||
* @param aNewLength -- new capacity of string in charSize units
|
||||
* @return void
|
||||
*/
|
||||
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
|
||||
PRBool result=PR_TRUE;
|
||||
if(aNewLength>aString.mCapacity) {
|
||||
result=Realloc(aString,aNewLength);
|
||||
if(aString.mStr)
|
||||
AddNullTerminator(aString);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
* to grow to a given size. The original contents ARE preserved.
|
||||
* @update gess 3/30/98
|
||||
* @param aNewLength -- new capacity of string in charSize units
|
||||
* @return void
|
||||
*/
|
||||
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
|
||||
PRBool result=PR_TRUE;
|
||||
if(aNewLength>aDest.mCapacity) {
|
||||
nsStr theTempStr;
|
||||
nsStr::Initialize(theTempStr,aDest.mCharSize);
|
||||
|
||||
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
|
||||
// the new strategy is, allocate exact size, double on grows
|
||||
if ( aDest.mCapacity ) {
|
||||
PRUint32 newCapacity = aDest.mCapacity;
|
||||
while ( newCapacity < aNewLength )
|
||||
newCapacity <<= 1;
|
||||
aNewLength = newCapacity;
|
||||
}
|
||||
#endif
|
||||
|
||||
result=EnsureCapacity(theTempStr,aNewLength);
|
||||
if(result) {
|
||||
if(aDest.mLength) {
|
||||
StrAppend(theTempStr,aDest,0,aDest.mLength);
|
||||
}
|
||||
Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
|
||||
aDest.mLength=theTempStr.mLength;
|
||||
aDest.mCapacity=theTempStr.mCapacity;
|
||||
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the contents of aDest with aSource, up to aCount of chars.
|
||||
* @update gess10/30/98
|
||||
* @param aDest is the nsStr that gets changed.
|
||||
* @param aSource is where chars are copied from
|
||||
* @param aCount is the number of chars copied from aSource
|
||||
*/
|
||||
void nsStr::StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
|
||||
if(&aDest!=&aSource){
|
||||
Truncate(aDest,0);
|
||||
StrAppend(aDest,aSource,anOffset,aCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method appends the given nsStr to this one. Note that we have to
|
||||
* pay attention to the underlying char-size of both structs.
|
||||
* @update gess10/30/98
|
||||
* @param aDest is the nsStr to be manipulated
|
||||
* @param aSource is where char are copied from
|
||||
* @aCount is the number of bytes to be copied
|
||||
*/
|
||||
void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
|
||||
if(anOffset<aSource.mLength){
|
||||
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
|
||||
if(0<theLength){
|
||||
|
||||
PRBool isBigEnough=PR_TRUE;
|
||||
if(aDest.mLength+theLength > aDest.mCapacity) {
|
||||
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
|
||||
}
|
||||
|
||||
if(isBigEnough) {
|
||||
//now append new chars, starting at offset
|
||||
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
|
||||
|
||||
aDest.mLength+=theLength;
|
||||
AddNullTerminator(aDest);
|
||||
NSSTR_SEEN(aDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
|
||||
* @update gess10/30/98
|
||||
* @param aDest is the nsStr that gets changed
|
||||
* @param aDestOffset is where in aDest the insertion is to occur
|
||||
* @param aSource is where chars are copied from
|
||||
* @param aSrcOffset is where in aSource chars are copied from
|
||||
* @param aCount is the number of chars from aSource to be inserted into aDest
|
||||
*/
|
||||
void nsStr::StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
|
||||
//there are a few cases for insert:
|
||||
// 1. You're inserting chars into an empty string (assign)
|
||||
// 2. You're inserting onto the end of a string (append)
|
||||
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
|
||||
if(0<aSource.mLength){
|
||||
if(aDest.mLength){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
|
||||
|
||||
if(aSrcOffset<aSource.mLength) {
|
||||
//here's the only new case we have to handle.
|
||||
//chars are really being inserted into our buffer...
|
||||
|
||||
if(aDest.mLength+theLength > aDest.mCapacity) {
|
||||
nsStr theTempStr;
|
||||
nsStr::Initialize(theTempStr,aDest.mCharSize);
|
||||
|
||||
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
|
||||
|
||||
if(isBigEnough) {
|
||||
if(aDestOffset) {
|
||||
StrAppend(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
|
||||
}
|
||||
|
||||
StrAppend(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
|
||||
|
||||
PRUint32 theRemains=aDest.mLength-aDestOffset;
|
||||
if(theRemains) {
|
||||
StrAppend(theTempStr,aDest,aDestOffset,theRemains); //next copy rightmost data
|
||||
}
|
||||
|
||||
Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
|
||||
aDest.mCapacity=theTempStr.mCapacity;
|
||||
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
//shift the chars right by theDelta...
|
||||
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
}
|
||||
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
AddNullTerminator(aDest);
|
||||
NSSTR_SEEN(aDest);
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
else StrAppend(aDest,aSource,0,aCount);
|
||||
}
|
||||
else StrAppend(aDest,aSource,0,aCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method deletes up to aCount chars from aDest
|
||||
* @update gess10/30/98
|
||||
* @param aDest is the nsStr to be manipulated
|
||||
* @param aDestOffset is where in aDest deletion is to occur
|
||||
* @param aCount is the number of chars to be deleted in aDest
|
||||
*/
|
||||
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
|
||||
PRUint32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
|
||||
if(aDestOffset+theLength<aDest.mLength) {
|
||||
|
||||
//if you're here, it means we're cutting chars out of the middle of the string...
|
||||
//so shift the chars left by theLength...
|
||||
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
AddNullTerminator(aDest);
|
||||
NSSTR_SEEN(aDest);
|
||||
}
|
||||
else 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(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
|
||||
aDest.mLength=aDestOffset;
|
||||
AddNullTerminator(aDest);
|
||||
NSSTR_SEEN(aDest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method forces the given string to upper or lowercase
|
||||
* @update gess1/7/99
|
||||
* @param aDest is the string you're going to change
|
||||
* @param aToUpper: if TRUE, then we go uppercase, otherwise we go lowercase
|
||||
* @return
|
||||
*/
|
||||
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
|
||||
// somehow UnicharUtil return failed, fallback to the old ascii only code
|
||||
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method removes characters from the given set from this string.
|
||||
* NOTE: aSet is a char*, and it's length is computed using strlen, which assumes null termination.
|
||||
*
|
||||
* @update gess 11/7/99
|
||||
* @param aDest
|
||||
* @param aSet
|
||||
* @param aEliminateLeading
|
||||
* @param aEliminateTrailing
|
||||
* @return nothing
|
||||
*/
|
||||
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
|
||||
|
||||
if((aDest.mLength>0) && aSet){
|
||||
PRInt32 theIndex=-1;
|
||||
PRInt32 theMax=aDest.mLength;
|
||||
PRInt32 theSetLen=nsCRT::strlen(aSet);
|
||||
|
||||
if(aEliminateLeading) {
|
||||
while(++theIndex<=theMax) {
|
||||
PRUnichar theChar=GetCharAt(aDest,theIndex);
|
||||
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
|
||||
if(kNotFound==thePos)
|
||||
break;
|
||||
}
|
||||
if(0<theIndex) {
|
||||
if(theIndex<theMax) {
|
||||
Delete(aDest,0,theIndex);
|
||||
}
|
||||
else 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,theSetLen);
|
||||
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;
|
||||
NSSTR_SEEN(aDest);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess1/7/99
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void nsStr::StripChars(nsStr& aDest,const char* aSet){
|
||||
if((0<aDest.mLength) && (aSet)) {
|
||||
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
|
||||
aDest.mLength=aNewLen;
|
||||
NSSTR_SEEN(aDest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Searching methods...
|
||||
**************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest for a given substring
|
||||
*
|
||||
* @update gess 2/04/00: added aCount argument to restrict search
|
||||
* @param aDest string to search
|
||||
* @param aTarget is the substring you're trying to find.
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search
|
||||
* @param aCount tells us how many iterations to make from offset; -1 means the full length of the string
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
|
||||
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
|
||||
|
||||
if(0<=theMaxPos) {
|
||||
|
||||
if(anOffset<0)
|
||||
anOffset=0;
|
||||
|
||||
if((0<aDest.mLength) && (anOffset<=theMaxPos) && (aTarget.mLength)) {
|
||||
|
||||
if(aCount<0)
|
||||
aCount = MaxInt(theMaxPos,1);
|
||||
|
||||
if(0<aCount) {
|
||||
|
||||
PRInt32 aDelta= (aDest.mCharSize == eOneByte) ? 1 : 2;
|
||||
const char* root = aDest.mStr;
|
||||
const char* left = root+(anOffset*aDelta);
|
||||
const char* last = left+((aCount)*aDelta);
|
||||
const char* max = root+(theMaxPos*aDelta);
|
||||
const char* right = (last<max) ? last : max;
|
||||
|
||||
while(left<=right){
|
||||
PRInt32 cmp=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(left,aTarget.mStr,aTarget.mLength,aIgnoreCase);
|
||||
if(0==cmp) {
|
||||
return (left-root)/aDelta;
|
||||
}
|
||||
left+=aDelta;
|
||||
} //while
|
||||
|
||||
} //if
|
||||
}
|
||||
} //if
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest for a given character
|
||||
*
|
||||
* @update gess 2/04/00: added aCount argument to restrict search
|
||||
* @param aDest string to search
|
||||
* @param char is the character you're trying to find.
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search
|
||||
* @param aCount tell us how many chars to search from offset
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
|
||||
return gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest for a character found in aSet.
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @param aDest string to search
|
||||
* @param aSet contains a list of chars to be searched for
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
|
||||
//NS_PRECONDITION(aSet.mLength!=1,kCallFindChar);
|
||||
|
||||
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
|
||||
PRInt32 thePos;
|
||||
|
||||
//Note that the search is inverted here. We're scanning aDest, one char at a time
|
||||
//but doing the search against the given set. That's why we use 0 as the offset below.
|
||||
if((0<aDest.mLength) && (0<aSet.mLength)){
|
||||
while(++index<(PRInt32)aDest.mLength) {
|
||||
PRUnichar theChar=GetCharAt(aDest,index);
|
||||
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
|
||||
if(kNotFound!=thePos)
|
||||
return index;
|
||||
} //while
|
||||
}
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Reverse Searching methods...
|
||||
**************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest (in reverse) for a given substring
|
||||
*
|
||||
* @update gess 2/18/00
|
||||
* @param aDest string to search
|
||||
* @param aTarget is the substring you're trying to find.
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search (counting from left)
|
||||
* @param aCount tell us how many iterations to perform from offset
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
|
||||
if(anOffset<0)
|
||||
anOffset=(PRInt32)aDest.mLength-1;
|
||||
|
||||
if(aCount<0)
|
||||
aCount = aDest.mLength;
|
||||
|
||||
if((0<aDest.mLength) && ((PRUint32)anOffset<aDest.mLength) && (aTarget.mLength)) {
|
||||
|
||||
if(0<aCount) {
|
||||
|
||||
PRInt32 aDelta = (aDest.mCharSize == eOneByte) ? 1 : 2;
|
||||
const char* root = aDest.mStr;
|
||||
const char* destLast = root+(aDest.mLength*aDelta); //pts to last char in aDest (likely null)
|
||||
|
||||
const char* rightmost = root+(anOffset*aDelta);
|
||||
const char* min = rightmost-((aCount-1)*aDelta);
|
||||
|
||||
const char* leftmost = (min<root) ? root: min;
|
||||
|
||||
while(leftmost<=rightmost) {
|
||||
//don't forget to divide by delta in next text (bug found by rhp)...
|
||||
if(aTarget.mLength<=PRUint32((destLast-rightmost)/aDelta)) {
|
||||
PRInt32 result=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(rightmost,aTarget.mStr,aTarget.mLength,aIgnoreCase);
|
||||
|
||||
if(0==result) {
|
||||
return (rightmost-root)/aDelta;
|
||||
}
|
||||
} //if
|
||||
rightmost-=aDelta;
|
||||
} //while
|
||||
}
|
||||
}
|
||||
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest (in reverse) for a given character
|
||||
*
|
||||
* @update gess 2/04/00
|
||||
* @param aDest string to search
|
||||
* @param char is the character you're trying to find.
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search; -1 means start at very end (mLength)
|
||||
* @param aCount tell us how many iterations to perform from offset; -1 means use full length.
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
|
||||
return gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This searches aDest (in reverese) for a character found in aSet.
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @param aDest string to search
|
||||
* @param aSet contains a list of chars to be searched for
|
||||
* @param aIgnorecase indicates case sensitivity of search
|
||||
* @param anOffset tells us where to start the search
|
||||
* @return index in aDest where member of aSet occurs, or -1 if not found
|
||||
*/
|
||||
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
|
||||
//NS_PRECONDITION(aSet.mLength!=1,kCallRFindChar);
|
||||
|
||||
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
|
||||
PRInt32 thePos;
|
||||
|
||||
//note that the search is inverted here. We're scanning aDest, one char at a time
|
||||
//but doing the search against the given set. That's why we use 0 as the offset below.
|
||||
if(0<aDest.mLength) {
|
||||
while(--index>=0) {
|
||||
PRUnichar theChar=GetCharAt(aDest,index);
|
||||
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
|
||||
if(kNotFound!=thePos)
|
||||
return index;
|
||||
} //while
|
||||
}
|
||||
return kNotFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare source and dest strings, up to an (optional max) number of chars
|
||||
* @param aDest is the first str to compare
|
||||
* @param aSource is the second str to compare
|
||||
* @param aCount -- if (-1), then we use length of longer string; if (0<aCount) then it gives the max # of chars to compare
|
||||
* @param aIgnorecase tells us whether to search with case sensitivity
|
||||
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
|
||||
*/
|
||||
PRInt32 nsStr::StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
|
||||
PRInt32 result=0;
|
||||
|
||||
if(aCount) {
|
||||
PRInt32 minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
|
||||
|
||||
if(0==minlen) {
|
||||
if ((aDest.mLength == 0) && (aSource.mLength == 0))
|
||||
return 0;
|
||||
if (aDest.mLength == 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
PRInt32 theCount = (aCount<0) ? minlen: MinInt(aCount,minlen);
|
||||
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,theCount,aIgnoreCase);
|
||||
|
||||
if (0==result) {
|
||||
if(-1==aCount) {
|
||||
|
||||
//Since the caller didn't give us a length to test, and minlen characters matched,
|
||||
//we have to assume that the longer string is greater.
|
||||
|
||||
if (aDest.mLength != aSource.mLength) {
|
||||
//we think they match, but we've only compared minlen characters.
|
||||
//if the string lengths are different, then they don't really match.
|
||||
result = (aDest.mLength<aSource.mLength) ? -1 : 1;
|
||||
}
|
||||
} //if
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the contents of dest at offset with contents of aSource
|
||||
*
|
||||
* @param aDest is the first str to compare
|
||||
* @param aSource is the second str to compare
|
||||
* @param aDestOffset is the offset within aDest where source should be copied
|
||||
* @return error code
|
||||
*/
|
||||
void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
|
||||
if(aDest.mLength && aSource.mLength) {
|
||||
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
|
||||
//if you're here, then both dest and source have valid lengths
|
||||
//and there's enough room in dest (at offset) to contain source.
|
||||
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
|
||||
|
||||
static int mAllocCount=0;
|
||||
mAllocCount++;
|
||||
|
||||
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
|
||||
//we're given the acount value in charunits; now scale up to next multiple.
|
||||
PRUint32 theNewCapacity=kDefaultStringSize;
|
||||
while(theNewCapacity<aCount){
|
||||
theNewCapacity<<=1;
|
||||
}
|
||||
|
||||
aDest.mCapacity=theNewCapacity++;
|
||||
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
|
||||
aDest.mStr = (char*)nsMemory::Alloc(theSize);
|
||||
#else
|
||||
// the new strategy is, allocate exact size, double on grows
|
||||
aDest.mCapacity = aCount;
|
||||
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
|
||||
#endif
|
||||
|
||||
if(aDest.mStr) {
|
||||
aDest.mOwnsBuffer=1;
|
||||
gStringAcquiredMemory=PR_TRUE;
|
||||
}
|
||||
else gStringAcquiredMemory=PR_FALSE;
|
||||
return gStringAcquiredMemory;
|
||||
}
|
||||
|
||||
PRBool nsStr::Free(nsStr& aDest){
|
||||
if(aDest.mStr){
|
||||
if(aDest.mOwnsBuffer){
|
||||
nsMemory::Free(aDest.mStr);
|
||||
}
|
||||
aDest.mStr=0;
|
||||
aDest.mOwnsBuffer=0;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
|
||||
|
||||
nsStr temp;
|
||||
memcpy(&temp,&aDest,sizeof(aDest));
|
||||
|
||||
PRBool result=Alloc(temp,aCount);
|
||||
if(result) {
|
||||
Free(aDest);
|
||||
aDest.mStr=temp.mStr;
|
||||
aDest.mCapacity=temp.mCapacity;
|
||||
aDest.mOwnsBuffer=temp.mOwnsBuffer;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve last memory error
|
||||
*
|
||||
* @update gess 10/11/99
|
||||
* @return memory error (usually returns PR_TRUE)
|
||||
*/
|
||||
PRBool nsStr::DidAcquireMemory(void) {
|
||||
return gStringAcquiredMemory;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
CBufDescriptor::CBufDescriptor(char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
|
||||
mBuffer=aString;
|
||||
mCharSize=eOneByte;
|
||||
mStackBased=aStackBased;
|
||||
mIsConst=PR_FALSE;
|
||||
mLength=mCapacity=0;
|
||||
if(aString && aCapacity>1) {
|
||||
mCapacity=aCapacity-1;
|
||||
mLength=(-1==aLength) ? strlen(aString) : aLength;
|
||||
if(mLength>PRInt32(mCapacity))
|
||||
mLength=mCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
CBufDescriptor::CBufDescriptor(const char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
|
||||
mBuffer=(char*)aString;
|
||||
mCharSize=eOneByte;
|
||||
mStackBased=aStackBased;
|
||||
mIsConst=PR_TRUE;
|
||||
mLength=mCapacity=0;
|
||||
if(aString && aCapacity>1) {
|
||||
mCapacity=aCapacity-1;
|
||||
mLength=(-1==aLength) ? strlen(aString) : aLength;
|
||||
if(mLength>PRInt32(mCapacity))
|
||||
mLength=mCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CBufDescriptor::CBufDescriptor(PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
|
||||
mBuffer=(char*)aString;
|
||||
mCharSize=eTwoByte;
|
||||
mStackBased=aStackBased;
|
||||
mLength=mCapacity=0;
|
||||
mIsConst=PR_FALSE;
|
||||
if(aString && aCapacity>1) {
|
||||
mCapacity=aCapacity-1;
|
||||
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
|
||||
if(mLength>PRInt32(mCapacity))
|
||||
mLength=mCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
|
||||
mBuffer=(char*)aString;
|
||||
mCharSize=eTwoByte;
|
||||
mStackBased=aStackBased;
|
||||
mLength=mCapacity=0;
|
||||
mIsConst=PR_TRUE;
|
||||
if(aString && aCapacity>1) {
|
||||
mCapacity=aCapacity-1;
|
||||
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
|
||||
if(mLength>PRInt32(mCapacity))
|
||||
mLength=mCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
PRUint32
|
||||
nsStr::HashCode(const nsStr& aDest)
|
||||
{
|
||||
if (aDest.mCharSize == eTwoByte)
|
||||
return nsCRT::HashCode(aDest.mUStr);
|
||||
else
|
||||
return nsCRT::HashCode(aDest.mStr);
|
||||
}
|
||||
|
||||
#ifdef NS_STR_STATS
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef XP_MAC
|
||||
#define isascii(c) ((unsigned)(c) < 0x80)
|
||||
#endif
|
||||
|
||||
void
|
||||
nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
|
||||
{
|
||||
PRInt32 printLen = (PRInt32)aDest.mLength;
|
||||
|
||||
if (aDest.mCharSize == eOneByte) {
|
||||
const char* chars = aDest.mStr;
|
||||
while (printLen-- && (!truncate || *chars != '\n')) {
|
||||
fputc(*chars++, out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const PRUnichar* chars = aDest.mUStr;
|
||||
while (printLen-- && (!truncate || *chars != '\n')) {
|
||||
if (isascii(*chars))
|
||||
fputc((char)(*chars++), out);
|
||||
else
|
||||
fputc('-', out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// String Usage Statistics Routines
|
||||
|
||||
static PLHashTable* gStringInfo = nsnull;
|
||||
PRLock* gStringInfoLock = nsnull;
|
||||
PRBool gNoStringInfo = PR_FALSE;
|
||||
|
||||
nsStringInfo::nsStringInfo(nsStr& str)
|
||||
: mCount(0)
|
||||
{
|
||||
nsStr::Initialize(mStr, str.mCharSize);
|
||||
nsStr::StrAssign(mStr, str, 0, -1);
|
||||
// nsStr::Print(mStr, stdout);
|
||||
// fputc('\n', stdout);
|
||||
}
|
||||
|
||||
PR_EXTERN(PRHashNumber)
|
||||
nsStr_Hash(const void* key)
|
||||
{
|
||||
nsStr* str = (nsStr*)key;
|
||||
return nsStr::HashCode(*str);
|
||||
}
|
||||
|
||||
PR_EXTERN(PRIntn)
|
||||
nsStr_Compare(const void *v1, const void *v2)
|
||||
{
|
||||
nsStr* str1 = (nsStr*)v1;
|
||||
nsStr* str2 = (nsStr*)v2;
|
||||
return nsStr::StrCompare(*str1, *str2, -1, PR_FALSE) == 0;
|
||||
}
|
||||
|
||||
nsStringInfo*
|
||||
nsStringInfo::GetInfo(nsStr& str)
|
||||
{
|
||||
if (gStringInfo == nsnull) {
|
||||
gStringInfo = PL_NewHashTable(1024,
|
||||
nsStr_Hash,
|
||||
nsStr_Compare,
|
||||
PL_CompareValues,
|
||||
NULL, NULL);
|
||||
gStringInfoLock = PR_NewLock();
|
||||
}
|
||||
PR_Lock(gStringInfoLock);
|
||||
nsStringInfo* info =
|
||||
(nsStringInfo*)PL_HashTableLookup(gStringInfo, &str);
|
||||
if (info == NULL) {
|
||||
gNoStringInfo = PR_TRUE;
|
||||
info = new nsStringInfo(str);
|
||||
if (info) {
|
||||
PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info);
|
||||
if (e == NULL) {
|
||||
delete info;
|
||||
info = NULL;
|
||||
}
|
||||
}
|
||||
gNoStringInfo = PR_FALSE;
|
||||
}
|
||||
PR_Unlock(gStringInfoLock);
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
nsStringInfo::Seen(nsStr& str)
|
||||
{
|
||||
if (!gNoStringInfo) {
|
||||
nsStringInfo* info = GetInfo(str);
|
||||
info->mCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsStringInfo::Report(FILE* out)
|
||||
{
|
||||
if (gStringInfo) {
|
||||
fprintf(out, "\n== String Stats\n");
|
||||
PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out);
|
||||
}
|
||||
}
|
||||
|
||||
PRIntn
|
||||
nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
nsStringInfo* entry = (nsStringInfo*)he->value;
|
||||
FILE* out = (FILE*)arg;
|
||||
|
||||
fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength);
|
||||
nsStr::Print(entry->mStr, out, PR_TRUE);
|
||||
fputc('\n', out);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
#endif // NS_STR_STATS
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
523
mozilla/string/obsolete/nsStr.h
Normal file
523
mozilla/string/obsolete/nsStr.h
Normal file
@@ -0,0 +1,523 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rick Gessner <rickg@netscape.com> (original author)
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
MODULE NOTES:
|
||||
|
||||
1. There are two philosophies to building string classes:
|
||||
A. Hide the underlying buffer & offer API's allow indirect iteration
|
||||
B. Reveal underlying buffer, risk corruption, but gain performance
|
||||
|
||||
We chose the option B for performance reasons.
|
||||
|
||||
2 Our internal buffer always holds capacity+1 bytes.
|
||||
|
||||
The nsStr struct is a simple structure (no methods) that contains
|
||||
the necessary info to be described as a string. This simple struct
|
||||
is manipulated by the static methods provided in this class.
|
||||
(Which effectively makes this a library that works on structs).
|
||||
|
||||
There are also object-based versions called nsString and nsAutoString
|
||||
which use nsStr but makes it look at feel like an object.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
ASSUMPTIONS:
|
||||
|
||||
1. nsStrings and nsAutoString are always null terminated. However,
|
||||
since it maintains a length byte, you can store NULL's inside
|
||||
the string. Just be careful passing such buffers to 3rd party
|
||||
API's that assume that NULL always terminate the buffer.
|
||||
|
||||
2. nsCStrings can be upsampled into nsString without data loss
|
||||
|
||||
3. Char searching is faster than string searching. Use char interfaces
|
||||
if your needs will allow it.
|
||||
|
||||
4. It's easy to use the stack for nsAutostring buffer storage (fast too!).
|
||||
See the CBufDescriptor class in this file.
|
||||
|
||||
5. If you don't provide the optional count argument to Append() and Insert(),
|
||||
the method will assume that the given buffer is terminated by the first
|
||||
NULL it encounters.
|
||||
|
||||
6. Downsampling from nsString to nsCString can be lossy -- avoid it if possible!
|
||||
|
||||
7. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to nsMemory::Free().
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
|
||||
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
|
||||
|
||||
The fundamental datatype in the string library is nsStr. It's a structure that
|
||||
provides the buffer storage and meta-info. It also provides a C-style library
|
||||
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
|
||||
|
||||
Here's a diagram of the class hierarchy:
|
||||
|
||||
nsStr
|
||||
|___nsString
|
||||
| |
|
||||
| ------nsAutoString
|
||||
|
|
||||
|___nsCString
|
||||
|
|
||||
------nsCAutoString
|
||||
|
||||
Why so many string classes? The 4 variants give you the control you need to
|
||||
determine the best class for your purpose. There are 2 dimensions to this
|
||||
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
|
||||
|
||||
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
|
||||
they may not stay that way. Like all nsString classes, autostrings will
|
||||
automatically grow to contain the data you provide. When autostrings
|
||||
grow beyond their intrinsic buffer, they switch to heap based allocations.
|
||||
(We avoid alloca to avoid considerable platform difficulties; see the
|
||||
GNU documentation for more details).
|
||||
|
||||
I should also briefly mention that all the string classes use a "memory agent"
|
||||
object to perform memory operations. This class proxies the standard nsMemory
|
||||
for actual memory calls, but knows the structure of nsStr making heap operations
|
||||
more localized.
|
||||
|
||||
|
||||
CHOOSING A STRING CLASS:
|
||||
|
||||
In order to choose a string class for you purpose, use this handy table:
|
||||
|
||||
heap-based stack-based
|
||||
-----------------------------------
|
||||
ascii data | nsCString nsCAutoString |
|
||||
|----------------------------------
|
||||
unicode data | nsString nsAutoString |
|
||||
-----------------------------------
|
||||
|
||||
|
||||
Note: The i18n folks will stenuously object if we get too carried away with the
|
||||
use of nsCString's that pass interface boundaries. Try to limit your
|
||||
use of these to external interfaces that demand them, or for your own
|
||||
private purposes in cases where they'll never be seen by humans.
|
||||
|
||||
|
||||
--- FAQ ---
|
||||
|
||||
Q. When should I use nsCString instead of nsString?
|
||||
|
||||
A. You should really try to stick with nsString, so that we stay as unicode
|
||||
compliant as possible. But there are cases where an interface you use requires
|
||||
a char*. In such cases, it's fair to use nsCString.
|
||||
|
||||
Q. I know that my string is going to be a certain size. Can I pre-size my nsString?
|
||||
|
||||
A. Yup, here's how:
|
||||
|
||||
{
|
||||
nsString mBuffer;
|
||||
mBuffer.SetCapacity(aReasonableSize);
|
||||
}
|
||||
|
||||
Q. Should nsAutoString or nsCAutoString ever live on the heap?
|
||||
|
||||
A. That would be counterproductive. The point of nsAutoStrings is to preallocate your
|
||||
buffers, and to auto-destroy the string when it goes out of scope.
|
||||
|
||||
Q. I already have a char*. Can I use the nsString functionality on that buffer?
|
||||
|
||||
A. Yes you can -- by using an intermediate class called CBufDescriptor.
|
||||
The CBufDescriptor class is used to tell nsString about an external buffer (heap or stack) to use
|
||||
instead of it's own internal buffers. Here's an example:
|
||||
|
||||
{
|
||||
char theBuffer[256];
|
||||
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
|
||||
nsCAutoString s3( theBufDescriptor );
|
||||
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
|
||||
}
|
||||
|
||||
The assignment statment to s3 will cause the given string to be written to your
|
||||
stack-based buffer via the normal nsString/nsCString interfaces. Cool, huh?
|
||||
Note however that just like any other nsStringXXX use, if you write more data
|
||||
than will fit in the buffer, a visit to the heap manager will be in order.
|
||||
|
||||
|
||||
Q. What is the simplest way to get from a char* to PRUnichar*?
|
||||
|
||||
A. The simplest way is by construction (or assignment):
|
||||
|
||||
{
|
||||
char* theBuf = "hello there";
|
||||
nsAutoString foo(theBuf);
|
||||
}
|
||||
|
||||
If you don't want the char* to be copied into the nsAutoString, the use a
|
||||
CBufDescriptor instead.
|
||||
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsMemory.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "plhash.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
#define kRadix10 (10)
|
||||
#define kRadix16 (16)
|
||||
#define kAutoDetect (100)
|
||||
#define kRadixUnknown (kAutoDetect+1)
|
||||
#define IGNORE_CASE (PR_TRUE)
|
||||
|
||||
const PRInt32 kDefaultStringSize = 64;
|
||||
const PRInt32 kNotFound = -1;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class NS_COM CBufDescriptor {
|
||||
public:
|
||||
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
|
||||
CBufDescriptor(const char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
|
||||
CBufDescriptor(PRUnichar* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
|
||||
CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
|
||||
|
||||
char* mBuffer;
|
||||
eCharSize mCharSize;
|
||||
PRUint32 mCapacity;
|
||||
PRInt32 mLength;
|
||||
PRBool mStackBased;
|
||||
PRBool mIsConst;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct NS_COM nsStr {
|
||||
|
||||
nsStr() {
|
||||
MOZ_COUNT_CTOR(nsStr);
|
||||
}
|
||||
|
||||
~nsStr() {
|
||||
MOZ_COUNT_DTOR(nsStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,eCharSize aCharSize);
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
|
||||
|
||||
/**
|
||||
* This method destroys the given nsStr, and *MAY*
|
||||
* deallocate it's memory depending on the setting
|
||||
* of the internal mOwnsBUffer flag.
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be manipulated
|
||||
* @param anAgent is the allocator to be used to the nsStr
|
||||
*/
|
||||
static void Destroy(nsStr& aDest);
|
||||
|
||||
/**
|
||||
* These methods are where memory allocation/reallocation occur.
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be manipulated
|
||||
* @param anAgent is the allocator to be used on the nsStr
|
||||
* @return
|
||||
*/
|
||||
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
|
||||
static PRBool GrowCapacity(nsStr& aString,PRUint32 aNewLength);
|
||||
|
||||
/**
|
||||
* These methods are used to append content to the given nsStr
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param aSource is the buffer to be copied from
|
||||
* @param anOffset tells us where in source to start copying
|
||||
* @param aCount tells us the (max) # of chars to copy
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
|
||||
|
||||
/**
|
||||
* These methods are used to assign contents of a source string to dest string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param aSource is the buffer to be copied from
|
||||
* @param anOffset tells us where in source to start copying
|
||||
* @param aCount tells us the (max) # of chars to copy
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
|
||||
|
||||
/**
|
||||
* These methods are used to insert content from source string to the dest nsStr
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param aDestOffset tells us where in dest to start insertion
|
||||
* @param aSource is the buffer to be copied from
|
||||
* @param aSrcOffset tells us where in source to start copying
|
||||
* @param aCount tells us the (max) # of chars to insert
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
|
||||
|
||||
/**
|
||||
* This method deletes chars from the given str.
|
||||
* The given allocator may choose to resize the str as well.
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be deleted from
|
||||
* @param aDestOffset tells us where in dest to start deleting
|
||||
* @param aCount tells us the (max) # of chars to delete
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
|
||||
|
||||
/**
|
||||
* This method is used to truncate the given string.
|
||||
* The given allocator may choose to resize the str as well (but it's not likely).
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param aDestOffset tells us where in dest to start insertion
|
||||
* @param aSource is the buffer to be copied from
|
||||
* @param aSrcOffset tells us where in source to start copying
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void 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 StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase);
|
||||
|
||||
/**
|
||||
* These methods scan the given string for 1 or more chars in a given direction
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be searched to
|
||||
* @param aSource (or aChar) is the substr we're looking to find
|
||||
* @param aIgnoreCase tells us whether to search in a case-sensitive manner
|
||||
* @param anOffset tells us where in the dest string to start searching
|
||||
* @return the index of the source (substr) in dest, or -1 (kNotFound) if not found.
|
||||
*/
|
||||
static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
|
||||
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
|
||||
static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
|
||||
|
||||
static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
|
||||
|
||||
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
|
||||
|
||||
static PRBool DidAcquireMemory(void);
|
||||
|
||||
/**
|
||||
* Returns a hash code for the string for use in a PLHashTable.
|
||||
*/
|
||||
static PRUint32 HashCode(const nsStr& aDest);
|
||||
|
||||
#ifdef NS_STR_STATS
|
||||
/**
|
||||
* Prints an nsStr. If truncate is true, the string is only printed up to
|
||||
* the first newline. (Note: The current implementation doesn't handle
|
||||
* non-ascii unicode characters.)
|
||||
*/
|
||||
static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE);
|
||||
#endif
|
||||
|
||||
PRUint32 mLength;
|
||||
PRUint32 mCapacity;
|
||||
eCharSize mCharSize;
|
||||
PRBool mOwnsBuffer;
|
||||
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
};
|
||||
|
||||
private:
|
||||
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
|
||||
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
|
||||
static PRBool Free(nsStr& aString);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************
|
||||
A couple of tiny helper methods used in the string classes.
|
||||
**************************************************************/
|
||||
|
||||
inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){
|
||||
return (anInt1<anInt2) ? anInt1 : anInt2;
|
||||
}
|
||||
|
||||
inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
|
||||
return (anInt1<anInt2) ? anInt2 : anInt1;
|
||||
}
|
||||
|
||||
inline void AddNullTerminator(nsStr& aDest) {
|
||||
if(eTwoByte==aDest.mCharSize)
|
||||
aDest.mUStr[aDest.mLength]=0;
|
||||
else aDest.mStr[aDest.mLength]=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
|
||||
*
|
||||
* Return the given buffer to the heap manager. Calls allocator::Free()
|
||||
* @return string length
|
||||
*/
|
||||
inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
|
||||
inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
|
||||
if(anIndex<aDest.mLength) {
|
||||
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NS_STR_STATS
|
||||
|
||||
class nsStringInfo {
|
||||
public:
|
||||
nsStringInfo(nsStr& str);
|
||||
~nsStringInfo() {}
|
||||
|
||||
static nsStringInfo* GetInfo(nsStr& str);
|
||||
|
||||
static void Seen(nsStr& str);
|
||||
|
||||
static void Report(FILE* out = stdout);
|
||||
|
||||
static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
protected:
|
||||
nsStr mStr;
|
||||
PRUint32 mCount;
|
||||
};
|
||||
|
||||
#define NSSTR_SEEN(str) nsStringInfo::Seen(str)
|
||||
|
||||
#else // !NS_STR_STATS
|
||||
|
||||
#define NSSTR_SEEN(str) /* nothing */
|
||||
|
||||
#endif // !NS_STR_STATS
|
||||
|
||||
#endif // _nsStr
|
||||
1798
mozilla/string/obsolete/nsString.cpp
Normal file
1798
mozilla/string/obsolete/nsString.cpp
Normal file
File diff suppressed because it is too large
Load Diff
629
mozilla/string/obsolete/nsString.h
Normal file
629
mozilla/string/obsolete/nsString.h
Normal file
@@ -0,0 +1,629 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rick Gessner <rickg@netscape.com> (original author)
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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"
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
|
||||
class NS_COM nsSubsumeCStr;
|
||||
|
||||
class NS_COM nsCString :
|
||||
public nsAWritableCString,
|
||||
public nsStr {
|
||||
|
||||
protected:
|
||||
virtual const void* Implementation() const { return "nsCString"; }
|
||||
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
|
||||
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsCString();
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsCString
|
||||
*/
|
||||
nsCString(const nsCString& aString);
|
||||
|
||||
explicit nsCString( const nsAReadableCString& );
|
||||
|
||||
explicit nsCString(const char*);
|
||||
nsCString(const char*, PRInt32);
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
explicit nsCString(nsSubsumeCStr& aSubsumeStr);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
virtual ~nsCString();
|
||||
|
||||
/**
|
||||
* Retrieve the length of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual PRUint32 Length() const { return mLength; }
|
||||
|
||||
/**
|
||||
* Retrieve the size of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
|
||||
|
||||
|
||||
/**
|
||||
* Call this method if you want to force a different string capacity
|
||||
* @update gess7/30/98
|
||||
* @param aLength -- contains new length for mStr
|
||||
* @return
|
||||
*/
|
||||
void SetLength(PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* Sets the new length of the string.
|
||||
* @param aLength is new string length.
|
||||
* @return nada
|
||||
*/
|
||||
void SetCapacity(PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* This method truncates this string to given length.
|
||||
*
|
||||
* @param anIndex -- new length of string
|
||||
* @return nada
|
||||
*/
|
||||
void Truncate(PRUint32 anIndex=0) {
|
||||
NS_ASSERTION(anIndex<=mLength, "Can't use |Truncate()| to make a string longer.");
|
||||
if ( anIndex < mLength )
|
||||
SetLength(anIndex);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Accessor methods...
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
|
||||
*/
|
||||
const char* GetBuffer(void) const;
|
||||
|
||||
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
|
||||
|
||||
/**********************************************************************
|
||||
Lexomorphic transforms...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase
|
||||
* @update gess 7/27/98
|
||||
*/
|
||||
void ToLowerCase();
|
||||
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase, and
|
||||
* stores them in aOut
|
||||
* @update gess 7/27/98
|
||||
* @param aOut is a string to contain result
|
||||
*/
|
||||
void ToLowerCase(nsCString& aString) const;
|
||||
|
||||
/**
|
||||
* Converts chars in this to uppercase
|
||||
* @update gess 7/27/98
|
||||
*/
|
||||
void ToUpperCase();
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase, and
|
||||
* stores them in a given output string
|
||||
* @update gess 7/27/98
|
||||
* @param aOut is a string to contain result
|
||||
*/
|
||||
void ToUpperCase(nsCString& aString) const;
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to remove all occurances of the
|
||||
* characters found in aSet from this string.
|
||||
*
|
||||
* @param aSet -- characters to be cut from this
|
||||
* @return *this
|
||||
*/
|
||||
void StripChars(const char* aSet);
|
||||
void StripChar(PRUnichar aChar,PRInt32 anOffset=0);
|
||||
void StripChar(char aChar,PRInt32 anOffset=0) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
|
||||
|
||||
/**
|
||||
* This method strips whitespace throughout the string
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
void StripWhitespace();
|
||||
|
||||
/**
|
||||
* swaps occurence of 1 string for another
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
void ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
|
||||
void ReplaceChar(const char* aSet,PRUnichar aNewChar);
|
||||
|
||||
void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue);
|
||||
void ReplaceSubstring(const char* aTarget,const char* aNewValue);
|
||||
|
||||
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
|
||||
* @param aEliminateLeading
|
||||
* @param aEliminateTrailing
|
||||
* @param aIgnoreQuotes
|
||||
* @return this
|
||||
*/
|
||||
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
|
||||
|
||||
/**
|
||||
* This method strips whitespace from string.
|
||||
* You can control whether whitespace is yanked from
|
||||
* start and end of string as well.
|
||||
*
|
||||
* @param aEliminateLeading controls stripping of leading ws
|
||||
* @param aEliminateTrailing controls stripping of trailing ws
|
||||
* @return this
|
||||
*/
|
||||
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
|
||||
|
||||
/**
|
||||
* This method strips whitespace from string.
|
||||
* You can control whether whitespace is yanked from
|
||||
* start and end of string as well.
|
||||
*
|
||||
* @param aEliminateLeading controls stripping of leading ws
|
||||
* @param aEliminateTrailing controls stripping of trailing ws
|
||||
* @return this
|
||||
*/
|
||||
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
|
||||
|
||||
/**********************************************************************
|
||||
string conversion methods...
|
||||
*********************************************************************/
|
||||
//#ifndef STANDALONE_STRING_TESTS
|
||||
operator char*() {return mStr;}
|
||||
operator const char*() const {return (const char*)mStr;}
|
||||
//#endif
|
||||
|
||||
/**
|
||||
* This method constructs a new nsCString that is a clone
|
||||
* of this string.
|
||||
*
|
||||
*/
|
||||
nsCString* ToNewString() const;
|
||||
|
||||
/**
|
||||
* Creates an ISOLatin1 clone of this string
|
||||
* Note that calls to this method should be matched with calls to 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;
|
||||
|
||||
|
||||
/**
|
||||
* Perform string to int conversion.
|
||||
* @param aErrorCode will contain error if one occurs
|
||||
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
|
||||
* @return int rep of string value, and possible (out) error code
|
||||
*/
|
||||
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String manipulation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* assign given string to this string
|
||||
* @param aStr: buffer to be assigned to this
|
||||
* @param aCount is the length of the given str (or -1) if you want me to determine its length
|
||||
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
|
||||
nsCString& operator=( const nsCString& aString ) { Assign(aString); return *this; }
|
||||
nsCString& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsCString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsCString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsCString& operator=( char aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
void AssignWithConversion(const PRUnichar*,PRInt32=-1);
|
||||
void AssignWithConversion( const nsString& aString );
|
||||
void AssignWithConversion( const nsAReadableString& aString );
|
||||
void AssignWithConversion(PRUnichar);
|
||||
|
||||
/*
|
||||
* Appends n characters from given string to this,
|
||||
*
|
||||
* @param aString is the source to be appended to this
|
||||
* @param aCount -- number of chars to copy; -1 tells us to compute the strlen for you
|
||||
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
|
||||
*
|
||||
* @return number of chars copied
|
||||
*/
|
||||
|
||||
void AppendWithConversion(const nsString&, PRInt32=-1);
|
||||
void AppendWithConversion(PRUnichar aChar);
|
||||
void AppendWithConversion( const nsAReadableString& aString );
|
||||
void AppendWithConversion(const PRUnichar*, PRInt32=-1);
|
||||
// Why no |AppendWithConversion(const PRUnichar*, PRInt32)|? --- now I know, because implicit construction hid the need for this routine
|
||||
void AppendInt(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
|
||||
void AppendFloat( double aFloat );
|
||||
|
||||
virtual void do_AppendFromReadable( const nsAReadableCString& );
|
||||
/*
|
||||
* 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;
|
||||
|
||||
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
|
||||
// Why no |InsertWithConversion(PRUnichar*)|?
|
||||
|
||||
virtual void do_InsertFromReadable( const nsAReadableCString&, PRUint32 );
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Searching methods...
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Search for given substring within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @param anOffset tells us where in this strig to start searching
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* Search for given char within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param anOffset tells us where in this strig to start searching
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return find pos in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* This method searches this string for the first character
|
||||
* found in the given charset
|
||||
* @param aString contains set of chars to be found
|
||||
* @param anOffset tells us where to start searching in this
|
||||
* @return -1 if not found, else the offset in this
|
||||
*/
|
||||
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
|
||||
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
|
||||
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
|
||||
|
||||
|
||||
/**
|
||||
* This methods scans the string backwards, looking for the given string
|
||||
* @param aString is substring to be sought in this
|
||||
* @param aIgnoreCase tells us whether or not to do caseless compare
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
/**
|
||||
* Search for given char within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param anOffset tells us where in this strig to start searching
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @return find pos in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* This method searches this string for the last character
|
||||
* found in the given string
|
||||
* @param aString contains set of chars to be found
|
||||
* @param anOffset tells us where to start searching in this
|
||||
* @return -1 if not found, else the offset in this
|
||||
*/
|
||||
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Comparison methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Compares a given string type to this string.
|
||||
* @update gess 7/27/98
|
||||
* @param S is the string to be compared
|
||||
* @param aIgnoreCase tells us how to treat case
|
||||
* @param aCount tells us how many chars to compare
|
||||
* @return -1,0,1
|
||||
*/
|
||||
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
void DebugDump(void) const;
|
||||
|
||||
|
||||
static void Recycle(nsCString* aString);
|
||||
static nsCString* CreateString(void);
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
|
||||
void operator=( PRUnichar );
|
||||
void AssignWithConversion( char );
|
||||
void AssignWithConversion( const char*, PRInt32=-1 );
|
||||
void AppendWithConversion( char );
|
||||
void InsertWithConversion( char, PRUint32 );
|
||||
};
|
||||
|
||||
// NS_DEF_STRING_COMPARISON_OPERATORS(nsCString, char)
|
||||
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCString, char)
|
||||
|
||||
extern NS_COM int fputs(const nsCString& aString, FILE* out);
|
||||
//ostream& operator<<(ostream& aStream,const nsCString& aString);
|
||||
//virtual void DebugDump(ostream& aStream) const;
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Here comes the AutoString class which uses internal memory
|
||||
(typically found on the stack) for its default buffer.
|
||||
If the buffer needs to grow, it gets reallocated on the heap.
|
||||
**************************************************************/
|
||||
|
||||
class NS_COM nsCAutoString : public nsCString {
|
||||
public:
|
||||
|
||||
virtual ~nsCAutoString();
|
||||
|
||||
nsCAutoString();
|
||||
explicit nsCAutoString(const nsCString& );
|
||||
explicit nsCAutoString(const nsAReadableCString& aString);
|
||||
explicit nsCAutoString(const char* aString);
|
||||
nsCAutoString(const char* aString,PRInt32 aLength);
|
||||
explicit nsCAutoString(const CBufDescriptor& aBuffer);
|
||||
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsCAutoString(const nsSubsumeCStr& aSubsumeStr); // AIX and VAC++ require a const
|
||||
#else
|
||||
explicit nsCAutoString(nsSubsumeCStr& aSubsumeStr);
|
||||
#endif // AIX || XP_OS2_VACPP
|
||||
|
||||
|
||||
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
|
||||
private:
|
||||
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
|
||||
public:
|
||||
nsCAutoString& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsCAutoString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsCAutoString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsCAutoString& operator=( char aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
/**
|
||||
* Retrieve the size of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
|
||||
|
||||
char mBuffer[kDefaultStringSize];
|
||||
};
|
||||
|
||||
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCAutoString, char)
|
||||
|
||||
/**
|
||||
* A helper class that converts a UCS2 string to UTF8
|
||||
*/
|
||||
class NS_COM NS_ConvertUCS2toUTF8
|
||||
: public nsCAutoString
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
NS_ConvertUCS2toUTF8( const PRUnichar* aString )
|
||||
{
|
||||
Append( aString, ~PRUint32(0) /* MAXINT */);
|
||||
}
|
||||
|
||||
NS_ConvertUCS2toUTF8( const PRUnichar* aString, PRUint32 aLength )
|
||||
{
|
||||
Append( aString, aLength );
|
||||
}
|
||||
|
||||
explicit
|
||||
NS_ConvertUCS2toUTF8( PRUnichar aChar )
|
||||
{
|
||||
Append( &aChar, 1 );
|
||||
}
|
||||
|
||||
explicit NS_ConvertUCS2toUTF8( const nsAReadableString& aString );
|
||||
|
||||
const char* get() const
|
||||
{
|
||||
return mStr;
|
||||
}
|
||||
|
||||
operator const char*() const // to be deprecated, prefer |get()|
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
protected:
|
||||
void Append( const PRUnichar* aString, PRUint32 aLength );
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
NS_ConvertUCS2toUTF8( char );
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************
|
||||
The subsumestr class is very unusual.
|
||||
It differs from a normal string in that it doesn't use normal
|
||||
copy semantics when another string is assign to this.
|
||||
Instead, it "steals" the contents of the source string.
|
||||
|
||||
This is very handy for returning nsString classes as part of
|
||||
an operator+(...) for example, in that it cuts down the number
|
||||
of copy operations that must occur.
|
||||
|
||||
You should probably not use this class unless you really know
|
||||
what you're doing.
|
||||
***************************************************************/
|
||||
class NS_COM nsSubsumeCStr : public nsCString {
|
||||
public:
|
||||
explicit nsSubsumeCStr(nsStr& aString);
|
||||
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
|
||||
nsSubsumeCStr& operator=( const nsSubsumeCStr& aString ) { Assign(aString); return *this; }
|
||||
nsSubsumeCStr& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeCStr& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeCStr& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsSubsumeCStr& operator=( char aChar ) { Assign(aChar); return *this; }
|
||||
private:
|
||||
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
2061
mozilla/string/obsolete/nsString2.cpp
Normal file
2061
mozilla/string/obsolete/nsString2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
743
mozilla/string/obsolete/nsString2.h
Normal file
743
mozilla/string/obsolete/nsString2.h
Normal file
@@ -0,0 +1,743 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rick Gessner <rickg@netscape.com> (original author)
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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"
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
#ifdef STANDALONE_MI_STRING_TESTS
|
||||
class nsAReadableString { public: virtual ~nsAReadableString() { } };
|
||||
class nsAWritableString : public nsAReadableString { public: virtual ~nsAWritableString() { } };
|
||||
#endif
|
||||
|
||||
class nsISizeOfHandler;
|
||||
|
||||
|
||||
#define nsString2 nsString
|
||||
#define nsAutoString2 nsAutoString
|
||||
|
||||
class NS_COM nsSubsumeStr;
|
||||
|
||||
class NS_COM nsString :
|
||||
public nsAWritableString,
|
||||
public nsStr {
|
||||
|
||||
protected:
|
||||
virtual const void* Implementation() const { return "nsString"; }
|
||||
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
|
||||
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsString();
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsString
|
||||
*/
|
||||
nsString(const nsString& aString);
|
||||
|
||||
explicit nsString(const nsAReadableString&);
|
||||
|
||||
explicit nsString(const PRUnichar*);
|
||||
nsString(const PRUnichar*, PRInt32);
|
||||
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ require a const here
|
||||
#else
|
||||
explicit nsString(nsSubsumeStr& aSubsumeStr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
virtual ~nsString();
|
||||
|
||||
/**
|
||||
* Retrieve the length of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual PRUint32 Length() const { return mLength; }
|
||||
|
||||
/**
|
||||
* Retrieve the size of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
|
||||
|
||||
|
||||
/**
|
||||
* Call this method if you want to force a different string length
|
||||
* @update gess7/30/98
|
||||
* @param aLength -- contains new length for mStr
|
||||
* @return
|
||||
*/
|
||||
void SetLength(PRUint32 aLength);
|
||||
|
||||
/**
|
||||
* Sets the new length of the string.
|
||||
* @param aLength is new string length.
|
||||
* @return nada
|
||||
*/
|
||||
void SetCapacity(PRUint32 aLength);
|
||||
|
||||
|
||||
/**
|
||||
* This method truncates this string to given length.
|
||||
*
|
||||
* @param anIndex -- new length of string
|
||||
* @return nada
|
||||
*/
|
||||
void Truncate(PRUint32 anIndex=0) {
|
||||
NS_ASSERTION(anIndex<=mLength, "Can't use |Truncate()| to make a string longer.");
|
||||
if ( anIndex < mLength )
|
||||
SetLength(anIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not the characters in this
|
||||
* string are in store as 1 or 2 byte (unicode) strings.
|
||||
*
|
||||
* @return TRUE if ordered.
|
||||
*/
|
||||
PRBool IsUnicode(void) const {
|
||||
PRBool result=PRBool(mCharSize==eTwoByte);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Getters/Setters...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
|
||||
*/
|
||||
const char* GetBuffer(void) const;
|
||||
const PRUnichar* GetUnicode(void) const;
|
||||
|
||||
/**
|
||||
* Set nth character.
|
||||
*/
|
||||
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Lexomorphic transforms...
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase
|
||||
* @update gess 7/27/98
|
||||
*/
|
||||
void ToLowerCase();
|
||||
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase, and
|
||||
* stores them in aOut
|
||||
* @update gess 7/27/98
|
||||
* @param aOut is a string to contain result
|
||||
*/
|
||||
void ToLowerCase(nsString& aString) const;
|
||||
|
||||
/**
|
||||
* Converts chars in this to uppercase
|
||||
* @update gess 7/27/98
|
||||
*/
|
||||
void ToUpperCase();
|
||||
|
||||
/**
|
||||
* Converts chars in this to lowercase, and
|
||||
* stores them in a given output string
|
||||
* @update gess 7/27/98
|
||||
* @param aOut is a string to contain result
|
||||
*/
|
||||
void ToUpperCase(nsString& aString) const;
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to remove all occurances of the
|
||||
* characters found in aSet from this string.
|
||||
*
|
||||
* @param aSet -- characters to be cut from this
|
||||
* @return *this
|
||||
*/
|
||||
void StripChars( const char* aSet );
|
||||
void StripChar( PRUnichar aChar, PRInt32 anOffset=0 );
|
||||
void StripChar( char aChar, PRInt32 anOffset=0 ) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
|
||||
void StripChar( PRInt32 anInt, PRInt32 anOffset=0 ) { StripChar((PRUnichar)anInt,anOffset); }
|
||||
|
||||
/**
|
||||
* This method strips whitespace throughout the string
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
void StripWhitespace();
|
||||
|
||||
/**
|
||||
* swaps occurence of 1 string for another
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
void ReplaceChar( PRUnichar anOldChar, PRUnichar aNewChar );
|
||||
void ReplaceChar( const char* aSet, PRUnichar aNewChar );
|
||||
|
||||
void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue );
|
||||
void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue );
|
||||
|
||||
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
|
||||
* @param aEliminateLeading
|
||||
* @param aEliminateTrailing
|
||||
* @param aIgnoreQuotes
|
||||
* @return this
|
||||
*/
|
||||
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
|
||||
|
||||
/**
|
||||
* This method strips whitespace from string.
|
||||
* You can control whether whitespace is yanked from
|
||||
* start and end of string as well.
|
||||
*
|
||||
* @param aEliminateLeading controls stripping of leading ws
|
||||
* @param aEliminateTrailing controls stripping of trailing ws
|
||||
* @return this
|
||||
*/
|
||||
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
|
||||
|
||||
/**
|
||||
* This method strips whitespace from string.
|
||||
* You can control whether whitespace is yanked from
|
||||
* start and end of string as well.
|
||||
*
|
||||
* @param aEliminateLeading controls stripping of leading ws
|
||||
* @param aEliminateTrailing controls stripping of trailing ws
|
||||
* @return this
|
||||
*/
|
||||
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
|
||||
|
||||
/**********************************************************************
|
||||
string conversion methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* This method constructs a new nsString is a clone of this string.
|
||||
*
|
||||
*/
|
||||
nsString* ToNewString() const;
|
||||
|
||||
/**
|
||||
* Creates an ISOLatin1 clone of this string
|
||||
* Note that calls to this method should be matched with calls to 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 null-terminated UTF8 string
|
||||
*/
|
||||
char* ToNewUTF8String() const;
|
||||
|
||||
/**
|
||||
* Creates a unicode clone of this string
|
||||
* Note that calls to this method should be matched with calls to 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;
|
||||
|
||||
/**
|
||||
* Perform string to int conversion.
|
||||
* @param aErrorCode will contain error if one occurs
|
||||
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
|
||||
* @return int rep of string value, and possible (out) error code
|
||||
*/
|
||||
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
String manipulation methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* assign given string to this string
|
||||
* @param aStr: buffer to be assigned to this
|
||||
* @param aCount is the length of the given str (or -1) if you want me to determine its length
|
||||
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
|
||||
|
||||
* @return this
|
||||
*/
|
||||
|
||||
nsString& operator=( const nsString& aString ) { Assign(aString); return *this; }
|
||||
nsString& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
void AssignWithConversion(char);
|
||||
void AssignWithConversion(const char*);
|
||||
void AssignWithConversion(const char*, PRInt32);
|
||||
|
||||
|
||||
/*
|
||||
* Appends n characters from given string to this,
|
||||
* This version computes the length of your given string
|
||||
*
|
||||
* @param aString is the source to be appended to this
|
||||
* @return number of chars copied
|
||||
*/
|
||||
|
||||
void AppendInt(PRInt32, PRInt32=10); //radix=8,10 or 16
|
||||
void AppendFloat(double);
|
||||
void AppendWithConversion(const char*, PRInt32=-1);
|
||||
void AppendWithConversion(char);
|
||||
|
||||
virtual void do_AppendFromElement( PRUnichar );
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
//void InsertWithConversion(char);
|
||||
void InsertWithConversion(const char*, PRUint32, PRInt32=-1);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Searching methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Search for given substring within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @param anOffset tells us where in this strig to start searching
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
/**
|
||||
* Search for given char within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param anOffset tells us where in this strig to start searching
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return find pos in string, or -1 (kNotFound)
|
||||
*/
|
||||
//PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
|
||||
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* This method searches this string for the first character
|
||||
* found in the given charset
|
||||
* @param aString contains set of chars to be found
|
||||
* @param anOffset tells us where to start searching in this
|
||||
* @return -1 if not found, else the offset in this
|
||||
*/
|
||||
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
|
||||
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
|
||||
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
|
||||
|
||||
|
||||
/**
|
||||
* This methods scans the string backwards, looking for the given string
|
||||
* @param aString is substring to be sought in this
|
||||
* @param aIgnoreCase tells us whether or not to do caseless compare
|
||||
* @param anOffset tells us where in this strig to start searching (counting from left)
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return offset in string, or -1 (kNotFound)
|
||||
*/
|
||||
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
/**
|
||||
* Search for given char within this string
|
||||
*
|
||||
* @param aString is substring to be sought in this
|
||||
* @param anOffset tells us where in this strig to start searching (counting from left)
|
||||
* @param aIgnoreCase selects case sensitivity
|
||||
* @param aCount tells us how many iterations to make starting at the given offset
|
||||
* @return find pos in string, or -1 (kNotFound)
|
||||
*/
|
||||
//PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
|
||||
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
|
||||
|
||||
/**
|
||||
* This method searches this string for the last character
|
||||
* found in the given string
|
||||
* @param aString contains set of chars to be found
|
||||
* @param anOffset tells us where in this strig to start searching (counting from left)
|
||||
* @return -1 if not found, else the offset in this
|
||||
*/
|
||||
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
|
||||
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Comparison methods...
|
||||
*********************************************************************/
|
||||
|
||||
/**
|
||||
* Compares a given string type to this string.
|
||||
* @update gess 7/27/98
|
||||
* @param S is the string to be compared
|
||||
* @param aIgnoreCase tells us how to treat case
|
||||
* @param aCount tells us how many chars to compare
|
||||
* @return -1,0,1
|
||||
*/
|
||||
|
||||
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRInt32 CompareWithConversion(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
|
||||
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsAtom(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
|
||||
|
||||
PRBool EqualsIgnoreCase(const nsString& aString) const;
|
||||
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
|
||||
|
||||
|
||||
/**
|
||||
* Determine if given buffer is plain ascii
|
||||
*
|
||||
* @param aBuffer -- if null, then we test *this, otherwise we test given buffer
|
||||
* @return TRUE if is all ascii chars or if strlen==0
|
||||
*/
|
||||
PRBool IsASCII(const PRUnichar* aBuffer=0);
|
||||
|
||||
void DebugDump(void) const;
|
||||
|
||||
/**
|
||||
* Determine if given char is a valid space character
|
||||
*
|
||||
* @param aChar is character to be tested
|
||||
* @return TRUE if is valid space char
|
||||
*/
|
||||
static PRBool IsSpace(PRUnichar ch);
|
||||
|
||||
/**
|
||||
* Determine if given char in valid alpha range
|
||||
*
|
||||
* @param aChar is character to be tested
|
||||
* @return TRUE if in alpha range
|
||||
*/
|
||||
static PRBool IsAlpha(PRUnichar ch);
|
||||
|
||||
/**
|
||||
* Determine if given char is valid digit
|
||||
*
|
||||
* @param aChar is character to be tested
|
||||
* @return TRUE if char is a valid digit
|
||||
*/
|
||||
static PRBool IsDigit(PRUnichar ch);
|
||||
|
||||
static void Recycle(nsString* aString);
|
||||
static nsString* CreateString(void);
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
|
||||
void operator=( char );
|
||||
void AssignWithConversion( PRUnichar );
|
||||
void AssignWithConversion( const PRUnichar*, PRInt32=-1 );
|
||||
void AppendWithConversion( PRUnichar );
|
||||
void AppendWithConversion( const PRUnichar*, PRInt32=-1 );
|
||||
void InsertWithConversion( const PRUnichar*, PRUint32, PRInt32=-1 );
|
||||
};
|
||||
|
||||
// NS_DEF_STRING_COMPARISON_OPERATORS(nsString, PRUnichar)
|
||||
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsString, PRUnichar)
|
||||
|
||||
extern NS_COM int fputs(const nsString& aString, FILE* out);
|
||||
//ostream& operator<<(ostream& aStream,const nsString& aString);
|
||||
//virtual void DebugDump(ostream& aStream) const;
|
||||
|
||||
/**************************************************************
|
||||
Here comes the AutoString class which uses internal memory
|
||||
(typically found on the stack) for its default buffer.
|
||||
If the buffer needs to grow, it gets reallocated on the heap.
|
||||
**************************************************************/
|
||||
|
||||
class NS_COM nsAutoString : public nsString {
|
||||
public:
|
||||
|
||||
virtual ~nsAutoString();
|
||||
nsAutoString();
|
||||
nsAutoString(const nsAutoString& aString);
|
||||
explicit nsAutoString(const nsAReadableString& aString);
|
||||
explicit nsAutoString(const nsString& aString);
|
||||
explicit nsAutoString(const PRUnichar* aString);
|
||||
nsAutoString(const PRUnichar* aString,PRInt32 aLength);
|
||||
explicit nsAutoString(PRUnichar aChar);
|
||||
explicit nsAutoString(const CBufDescriptor& aBuffer);
|
||||
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsAutoString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ requires a const
|
||||
#else
|
||||
explicit nsAutoString(nsSubsumeStr& aSubsumeStr);
|
||||
#endif // AIX || XP_OS2_VACPP
|
||||
|
||||
|
||||
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
|
||||
private:
|
||||
void operator=( char ); // NOT TO BE IMPLEMENTED
|
||||
public:
|
||||
nsAutoString& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsAutoString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsAutoString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsAutoString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
/**
|
||||
* Retrieve the size of this string
|
||||
* @return string length
|
||||
*/
|
||||
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
|
||||
|
||||
char mBuffer[kDefaultStringSize<<eTwoByte];
|
||||
};
|
||||
|
||||
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsAutoString, PRUnichar)
|
||||
|
||||
class NS_COM NS_ConvertASCIItoUCS2
|
||||
: public nsAutoString
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
public:
|
||||
explicit NS_ConvertASCIItoUCS2( const char* );
|
||||
NS_ConvertASCIItoUCS2( const char*, PRUint32 );
|
||||
explicit NS_ConvertASCIItoUCS2( char );
|
||||
|
||||
const PRUnichar* get() const { return GetUnicode(); }
|
||||
|
||||
operator const PRUnichar*() const
|
||||
{
|
||||
return GetUnicode();
|
||||
}
|
||||
|
||||
operator nsLiteralString() const
|
||||
{
|
||||
return nsLiteralString(mUStr, mLength);
|
||||
}
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
NS_ConvertASCIItoUCS2( PRUnichar );
|
||||
};
|
||||
|
||||
#define NS_ConvertToString NS_ConvertASCIItoUCS2
|
||||
|
||||
#if 0
|
||||
inline
|
||||
nsAutoString
|
||||
NS_ConvertToString( const char* aCString )
|
||||
{
|
||||
nsAutoString result;
|
||||
result.AssignWithConversion(aCString);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
nsAutoString
|
||||
NS_ConvertToString( const char* aCString, PRUint32 aLength )
|
||||
{
|
||||
nsAutoString result;
|
||||
result.AssignWithConversion(aCString, aLength);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
class NS_COM NS_ConvertUTF8toUCS2
|
||||
: public nsAutoString
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
NS_ConvertUTF8toUCS2( const char* aCString )
|
||||
{
|
||||
Init( aCString, ~PRUint32(0) /* MAXINT */ );
|
||||
}
|
||||
|
||||
NS_ConvertUTF8toUCS2( const char* aCString, PRUint32 aLength )
|
||||
{
|
||||
Init( aCString, aLength );
|
||||
}
|
||||
|
||||
explicit
|
||||
NS_ConvertUTF8toUCS2( char aChar )
|
||||
{
|
||||
Init( &aChar, 1 );
|
||||
}
|
||||
|
||||
operator const PRUnichar*() const
|
||||
{
|
||||
return GetUnicode();
|
||||
}
|
||||
|
||||
protected:
|
||||
void Init( const char* aCString, PRUint32 aLength );
|
||||
|
||||
private:
|
||||
NS_ConvertUTF8toUCS2( PRUnichar );
|
||||
};
|
||||
|
||||
/***************************************************************
|
||||
The subsumestr class is very unusual.
|
||||
It differs from a normal string in that it doesn't use normal
|
||||
copy semantics when another string is assign to this.
|
||||
Instead, it "steals" the contents of the source string.
|
||||
|
||||
This is very handy for returning nsString classes as part of
|
||||
an operator+(...) for example, in that it cuts down the number
|
||||
of copy operations that must occur.
|
||||
|
||||
You should probably not use this class unless you really know
|
||||
what you're doing.
|
||||
***************************************************************/
|
||||
class NS_COM nsSubsumeStr : public nsString {
|
||||
public:
|
||||
nsSubsumeStr();
|
||||
explicit nsSubsumeStr(nsStr& aString);
|
||||
nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
int Subsume(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
|
||||
nsSubsumeStr& operator=( const nsSubsumeStr& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsSubsumeStr& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
|
||||
private:
|
||||
void operator=( char ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
163
mozilla/string/obsolete/nsXPIDLString.cpp
Normal file
163
mozilla/string/obsolete/nsXPIDLString.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "plstr.h"
|
||||
|
||||
// If the allocator changes, fix it here.
|
||||
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsMemory::Alloc((__len) * sizeof(PRUnichar)))
|
||||
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsMemory::Alloc((__len) * sizeof(char)))
|
||||
#define XPIDL_FREE(__ptr) (nsMemory::Free(__ptr))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLString
|
||||
|
||||
nsXPIDLString::~nsXPIDLString()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
PRUnichar*
|
||||
nsXPIDLString::Copy(const PRUnichar* aString)
|
||||
{
|
||||
NS_ASSERTION(aString, "null ptr");
|
||||
if (! aString)
|
||||
return 0;
|
||||
|
||||
PRInt32 len = 0;
|
||||
|
||||
{
|
||||
const PRUnichar* p = aString;
|
||||
while (*p++)
|
||||
len++;
|
||||
}
|
||||
|
||||
PRUnichar* result = XPIDL_STRING_ALLOC(len + 1);
|
||||
if (result) {
|
||||
PRUnichar* q = result;
|
||||
while (*aString) {
|
||||
*q = *aString;
|
||||
q++;
|
||||
aString++;
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PRUnichar**
|
||||
nsXPIDLString::StartAssignmentByValue()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_TRUE;
|
||||
return &mBuf;
|
||||
}
|
||||
|
||||
|
||||
const PRUnichar**
|
||||
nsXPIDLString::StartAssignmentByReference()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
return (const PRUnichar**) &mBuf;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLCString
|
||||
|
||||
nsXPIDLCString::~nsXPIDLCString()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLCString& nsXPIDLCString::operator =(const char* aCString)
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
if (aCString) {
|
||||
mBuf = Copy(aCString);
|
||||
mBufOwner = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsXPIDLCString::Copy(const char* aCString)
|
||||
{
|
||||
NS_ASSERTION(aCString, "null ptr");
|
||||
if (! aCString)
|
||||
return 0;
|
||||
|
||||
PRInt32 len = PL_strlen(aCString);
|
||||
char* result = XPIDL_CSTRING_ALLOC(len + 1);
|
||||
if (result)
|
||||
PL_strcpy(result, aCString);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char**
|
||||
nsXPIDLCString::StartAssignmentByValue()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_TRUE;
|
||||
return &mBuf;
|
||||
}
|
||||
|
||||
|
||||
const char**
|
||||
nsXPIDLCString::StartAssignmentByReference()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
return (const char**) &mBuf;
|
||||
}
|
||||
|
||||
|
||||
382
mozilla/string/obsolete/nsXPIDLString.h
Normal file
382
mozilla/string/obsolete/nsXPIDLString.h
Normal file
@@ -0,0 +1,382 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A set of string wrapper classes that ease transition to use of XPIDL
|
||||
interfaces. nsXPIDLString and nsXPIDLCString are to XPIDL `wstring'
|
||||
and `string' out params as nsCOMPtr is to generic XPCOM interface
|
||||
pointers. They help you deal with object ownership.
|
||||
|
||||
Consider the following interface:
|
||||
|
||||
interface nsIFoo {
|
||||
attribute string Bar;
|
||||
};
|
||||
|
||||
This will generate the following C++ header file:
|
||||
|
||||
class nsIFoo {
|
||||
NS_IMETHOD SetBar(const PRUnichar* aValue);
|
||||
NS_IMETHOD GetBar(PRUnichar* *aValue);
|
||||
};
|
||||
|
||||
The GetBar() method will allocate a copy of the nsIFoo object's
|
||||
"bar" attribute, and leave you to deal with freeing it:
|
||||
|
||||
nsIFoo* aFoo; // assume we get this somehow
|
||||
PRUnichar* bar;
|
||||
aFoo->GetFoo(&bar);
|
||||
// Use bar here...
|
||||
printf("bar is %s!\n", bar);
|
||||
nsMemory::Free(bar);
|
||||
|
||||
This makes your life harder, because you need to convolute your code
|
||||
to ensure that you don't leak `bar'.
|
||||
|
||||
Enter nsXPIDLString, which manages the ownership of the allocated
|
||||
string, and automatically destroys it when the nsXPIDLString goes
|
||||
out of scope:
|
||||
|
||||
nsIFoo* aFoo;
|
||||
nsXPIDLString bar;
|
||||
aFoo->GetFoo( getter_Copies(bar) );
|
||||
// Use bar here...
|
||||
printf("bar is %s!\n", (const char*) bar);
|
||||
// no need to remember to nsMemory::Free().
|
||||
|
||||
Like nsCOMPtr, nsXPIDLString uses some syntactic sugar to make it
|
||||
painfully clear exactly what the code expects. You need to wrap an
|
||||
nsXPIDLString object with either `getter_Copies()' or
|
||||
`getter_Shares()' before passing it to a getter: these tell the
|
||||
nsXPIDLString how ownership is being handled.
|
||||
|
||||
In the case of `getter_Copies()', the callee is allocating a copy
|
||||
(which is usually the case). In the case of `getter_Shares()', the
|
||||
callee is returning a const reference to `the real deal' (this can
|
||||
be done using the [shared] attribute in XPIDL).
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsXPIDLString_h__
|
||||
#define nsXPIDLString_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCom.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
#ifndef __PRUNICHAR__
|
||||
#define __PRUNICHAR__
|
||||
typedef PRUint16 PRUnichar;
|
||||
#endif /* __PRUNICHAR__ */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLString
|
||||
//
|
||||
// A wrapper for Unicode strings. With the |getter_Copies()| and
|
||||
// |getter_Shares()| helper functions, this can be used instead of
|
||||
// the "naked" |PRUnichar*| interface for |wstring| parameters in
|
||||
// XPIDL interfaces.
|
||||
//
|
||||
|
||||
class NS_COM nsXPIDLString {
|
||||
private:
|
||||
PRUnichar* mBuf;
|
||||
PRBool mBufOwner;
|
||||
|
||||
PRUnichar** StartAssignmentByValue();
|
||||
const PRUnichar** StartAssignmentByReference();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new, uninitialized wrapper for a Unicode string.
|
||||
*/
|
||||
nsXPIDLString() : mBuf(0), mBufOwner(PR_FALSE) {}
|
||||
|
||||
virtual ~nsXPIDLString();
|
||||
|
||||
/**
|
||||
* Return a reference to the immutable Unicode string.
|
||||
*/
|
||||
operator const PRUnichar*() const { return get(); }
|
||||
|
||||
/**
|
||||
* Return a reference to the immutable Unicode string.
|
||||
*/
|
||||
const PRUnichar* get() const { return mBuf; }
|
||||
|
||||
/**
|
||||
* Make a copy of the Unicode string. Use this function in the
|
||||
* callee to ensure that the correct memory allocator is used.
|
||||
*/
|
||||
static PRUnichar* Copy(const PRUnichar* aString);
|
||||
|
||||
// A helper class for assignment-by-value. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterCopies {
|
||||
private:
|
||||
nsXPIDLString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterCopies(nsXPIDLString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator PRUnichar**() {
|
||||
return mXPIDLString.StartAssignmentByValue();
|
||||
}
|
||||
|
||||
friend GetterCopies getter_Copies(nsXPIDLString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterCopies;
|
||||
|
||||
// A helper class for assignment-by-reference. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterShares {
|
||||
private:
|
||||
nsXPIDLString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterShares(nsXPIDLString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator const PRUnichar**() {
|
||||
return mXPIDLString.StartAssignmentByReference();
|
||||
}
|
||||
|
||||
friend GetterShares getter_Shares(nsXPIDLString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterShares;
|
||||
|
||||
private:
|
||||
// not to be implemented
|
||||
nsXPIDLString(nsXPIDLString& /* aXPIDLString */) {}
|
||||
void operator=(nsXPIDLString& /* aXPIDLString */) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLString object that is to
|
||||
* receive an |out| value.
|
||||
*/
|
||||
inline nsXPIDLString::GetterCopies
|
||||
getter_Copies(nsXPIDLString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLString::GetterCopies(aXPIDLString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLString object that is to
|
||||
* receive a |[shared] out| value.
|
||||
*/
|
||||
inline nsXPIDLString::GetterShares
|
||||
getter_Shares(nsXPIDLString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLString::GetterShares(aXPIDLString);
|
||||
}
|
||||
|
||||
|
||||
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
|
||||
inline
|
||||
PRBool
|
||||
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
|
||||
{
|
||||
return lhs == NS_STATIC_CAST(const PRUnichar*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const PRUnichar*, lhs) == rhs;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(int lhs, const nsXPIDLString& rhs)
|
||||
{
|
||||
return NS_REINTERPRET_CAST(PRUnichar*, lhs) == NS_STATIC_CAST(const PRUnichar*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLString& lhs, int rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const PRUnichar*, lhs) == NS_REINTERPRET_CAST(PRUnichar*, rhs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLCString
|
||||
//
|
||||
// A wrapper for Unicode strings. With the |getter_Copies()| and
|
||||
// |getter_Shares()| helper functions, this can be used instead of
|
||||
// the "naked" |char*| interface for |string| parameters in XPIDL
|
||||
// interfaces.
|
||||
//
|
||||
|
||||
class NS_COM nsXPIDLCString {
|
||||
private:
|
||||
char* mBuf;
|
||||
PRBool mBufOwner;
|
||||
|
||||
char** StartAssignmentByValue();
|
||||
const char** StartAssignmentByReference();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new, uninitialized wrapper for a single-byte string.
|
||||
*/
|
||||
nsXPIDLCString() : mBuf(0), mBufOwner(PR_FALSE) {}
|
||||
|
||||
virtual ~nsXPIDLCString();
|
||||
|
||||
/**
|
||||
* Assign a single-byte string to this wrapper. Copies
|
||||
* and owns the result.
|
||||
*/
|
||||
nsXPIDLCString& operator=(const char* aString);
|
||||
|
||||
/**
|
||||
* Return a reference to the immutable single-byte string.
|
||||
*/
|
||||
operator const char*() const { return get(); }
|
||||
|
||||
/**
|
||||
* Return a reference to the immutable single-byte string.
|
||||
*/
|
||||
const char* get() const { return mBuf; }
|
||||
|
||||
/**
|
||||
* Make a copy of the single-byte string. Use this function in the
|
||||
* callee to ensure that the correct memory allocator is used.
|
||||
*/
|
||||
static char* Copy(const char* aString);
|
||||
|
||||
// A helper class for assignment-by-value. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterCopies {
|
||||
private:
|
||||
nsXPIDLCString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterCopies(nsXPIDLCString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator char**() {
|
||||
return mXPIDLString.StartAssignmentByValue();
|
||||
}
|
||||
|
||||
friend GetterCopies getter_Copies(nsXPIDLCString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterCopies;
|
||||
|
||||
// A helper class for assignment-by-reference. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterShares {
|
||||
private:
|
||||
nsXPIDLCString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterShares(nsXPIDLCString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator const char**() {
|
||||
return mXPIDLString.StartAssignmentByReference();
|
||||
}
|
||||
|
||||
friend GetterShares getter_Shares(nsXPIDLCString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterShares;
|
||||
|
||||
private:
|
||||
// not to be implemented
|
||||
nsXPIDLCString(nsXPIDLCString& /* aXPIDLString */) {}
|
||||
void operator=(nsXPIDLCString& /* aXPIDLCString */) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLCString object that is to
|
||||
* receive an |out| value.
|
||||
*/
|
||||
inline nsXPIDLCString::GetterCopies
|
||||
getter_Copies(nsXPIDLCString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLCString::GetterCopies(aXPIDLString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLCString object that is to
|
||||
* receive a |[shared] out| value.
|
||||
*/
|
||||
inline nsXPIDLCString::GetterShares
|
||||
getter_Shares(nsXPIDLCString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLCString::GetterShares(aXPIDLString);
|
||||
}
|
||||
|
||||
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
|
||||
inline
|
||||
PRBool
|
||||
operator==(const char* lhs, const nsXPIDLCString& rhs)
|
||||
{
|
||||
return lhs == NS_STATIC_CAST(const char*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLCString& lhs, const char* rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const char*, lhs) == rhs;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(int lhs, const nsXPIDLCString& rhs)
|
||||
{
|
||||
return NS_REINTERPRET_CAST(char*, lhs) == NS_STATIC_CAST(const char*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLCString& lhs, int rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const char*, lhs) == NS_REINTERPRET_CAST(char*, rhs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // nsXPIDLString_h__
|
||||
1549
mozilla/string/public/nsAReadableString.h
Normal file
1549
mozilla/string/public/nsAReadableString.h
Normal file
File diff suppressed because it is too large
Load Diff
882
mozilla/string/public/nsAWritableString.h
Normal file
882
mozilla/string/public/nsAWritableString.h
Normal file
@@ -0,0 +1,882 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*/
|
||||
|
||||
#ifndef nsAWritableString_h___
|
||||
#define nsAWritableString_h___
|
||||
|
||||
// See also...
|
||||
#ifndef nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
#endif
|
||||
|
||||
|
||||
template <class CharT>
|
||||
struct nsWritableFragment
|
||||
{
|
||||
CharT* mStart;
|
||||
CharT* mEnd;
|
||||
void* mFragmentIdentifier;
|
||||
|
||||
nsWritableFragment()
|
||||
: mStart(0), mEnd(0), mFragmentIdentifier(0)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT> class basic_nsAWritableString;
|
||||
|
||||
template <class CharT>
|
||||
class nsWritingIterator
|
||||
// : public bidirectional_iterator_tag
|
||||
{
|
||||
public:
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef CharT value_type;
|
||||
typedef CharT* pointer;
|
||||
typedef CharT& reference;
|
||||
// typedef bidirectional_iterator_tag iterator_category;
|
||||
|
||||
private:
|
||||
friend class basic_nsAWritableString<CharT>;
|
||||
|
||||
nsWritableFragment<CharT> mFragment;
|
||||
CharT* mPosition;
|
||||
basic_nsAWritableString<CharT>* mOwningString;
|
||||
|
||||
nsWritingIterator( nsWritableFragment<CharT>& aFragment,
|
||||
CharT* aStartingPosition,
|
||||
basic_nsAWritableString<CharT>& aOwningString )
|
||||
: mFragment(aFragment),
|
||||
mPosition(aStartingPosition),
|
||||
mOwningString(&aOwningString)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
public:
|
||||
nsWritingIterator() { }
|
||||
// nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
|
||||
// nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
|
||||
|
||||
inline void normalize_forward();
|
||||
inline void normalize_backward();
|
||||
|
||||
pointer
|
||||
get() const
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
|
||||
// don't like this when |CharT| is a type without members.
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
#endif
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
operator++()
|
||||
{
|
||||
++mPosition;
|
||||
normalize_forward();
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>
|
||||
operator++( int )
|
||||
{
|
||||
nsWritingIterator<CharT> result(*this);
|
||||
++mPosition;
|
||||
normalize_forward();
|
||||
return result;
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
operator--()
|
||||
{
|
||||
normalize_backward();
|
||||
--mPosition;
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>
|
||||
operator--( int )
|
||||
{
|
||||
nsWritingIterator<CharT> result(*this);
|
||||
normalize_backward();
|
||||
--mPosition;
|
||||
return result;
|
||||
}
|
||||
|
||||
const nsWritableFragment<CharT>&
|
||||
fragment() const
|
||||
{
|
||||
return mFragment;
|
||||
}
|
||||
|
||||
difference_type
|
||||
size_forward() const
|
||||
{
|
||||
return mFragment.mEnd - mPosition;
|
||||
}
|
||||
|
||||
difference_type
|
||||
size_backward() const
|
||||
{
|
||||
return mPosition - mFragment.mStart;
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
advance( difference_type n )
|
||||
{
|
||||
while ( n > 0 )
|
||||
{
|
||||
difference_type one_hop = NS_MIN(n, size_forward());
|
||||
|
||||
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
|
||||
// perhaps I should |break| if |!one_hop|?
|
||||
|
||||
mPosition += one_hop;
|
||||
normalize_forward();
|
||||
n -= one_hop;
|
||||
}
|
||||
|
||||
while ( n < 0 )
|
||||
{
|
||||
normalize_backward();
|
||||
difference_type one_hop = NS_MAX(n, -size_backward());
|
||||
|
||||
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
|
||||
// perhaps I should |break| if |!one_hop|?
|
||||
|
||||
mPosition += one_hop;
|
||||
n -= one_hop;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Really don't want to call these two operations |+=| and |-=|.
|
||||
* Would prefer a single function, e.g., |advance|, which doesn't imply a constant time operation.
|
||||
*
|
||||
* We'll get rid of these as soon as we can.
|
||||
*/
|
||||
nsWritingIterator<CharT>&
|
||||
operator+=( difference_type n ) // deprecated
|
||||
{
|
||||
return advance(n);
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
operator-=( difference_type n ) // deprecated
|
||||
{
|
||||
return advance(-n);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
write( const value_type* s, PRUint32 n )
|
||||
{
|
||||
NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
|
||||
|
||||
n = NS_MIN(n, PRUint32(size_forward()));
|
||||
nsCharTraits<value_type>::move(mPosition, s, n);
|
||||
advance( difference_type(n) );
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <class CharT>
|
||||
nsWritingIterator<CharT>&
|
||||
nsWritingIterator<CharT>::advance( difference_type n )
|
||||
{
|
||||
while ( n > 0 )
|
||||
{
|
||||
difference_type one_hop = NS_MIN(n, size_forward());
|
||||
|
||||
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
|
||||
// perhaps I should |break| if |!one_hop|?
|
||||
|
||||
mPosition += one_hop;
|
||||
normalize_forward();
|
||||
n -= one_hop;
|
||||
}
|
||||
|
||||
while ( n < 0 )
|
||||
{
|
||||
normalize_backward();
|
||||
difference_type one_hop = NS_MAX(n, -size_backward());
|
||||
|
||||
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
|
||||
// perhaps I should |break| if |!one_hop|?
|
||||
|
||||
mPosition += one_hop;
|
||||
n -= one_hop;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
This file defines the abstract interfaces |nsAWritableString| and
|
||||
|nsAWritableCString|.
|
||||
|
||||
|nsAWritableString| is a string of |PRUnichar|s. |nsAWritableCString| (note the
|
||||
'C') is a string of |char|s.
|
||||
*/
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsAWritableString
|
||||
: public basic_nsAReadableString<CharT>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
// friend class nsWritingIterator<CharT>;
|
||||
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef PRUint32 size_type;
|
||||
typedef PRUint32 index_type;
|
||||
|
||||
typedef nsWritingIterator<CharT> iterator;
|
||||
|
||||
// basic_nsAWritableString(); // auto-generated default constructor OK (we're abstract anyway)
|
||||
// basic_nsAWritableString( const basic_nsAWritableString<CharT>& ); // auto-generated copy-constructor OK (again, only because we're abstract)
|
||||
// ~basic_nsAWritableString(); // auto-generated destructor OK
|
||||
// see below for copy-assignment operator
|
||||
|
||||
virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
|
||||
|
||||
/**
|
||||
* Note: measure -- should the |BeginWriting| and |EndWriting| be |inline|?
|
||||
*/
|
||||
nsWritingIterator<CharT>&
|
||||
BeginWriting( nsWritingIterator<CharT>& aResult )
|
||||
{
|
||||
aResult.mOwningString = this;
|
||||
GetWritableFragment(aResult.mFragment, kFirstFragment);
|
||||
aResult.mPosition = aResult.mFragment.mStart;
|
||||
aResult.normalize_forward();
|
||||
return aResult;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
nsWritingIterator<CharT>
|
||||
BeginWriting()
|
||||
{
|
||||
nsWritingIterator<CharT> result;
|
||||
return BeginWriting(result); // copies (since I return a value, not a reference)
|
||||
}
|
||||
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
EndWriting( nsWritingIterator<CharT>& aResult )
|
||||
{
|
||||
aResult.mOwningString = this;
|
||||
GetWritableFragment(aResult.mFragment, kLastFragment);
|
||||
aResult.mPosition = aResult.mFragment.mEnd;
|
||||
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
|
||||
return aResult;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
nsWritingIterator<CharT>
|
||||
EndWriting()
|
||||
{
|
||||
nsWritingIterator<CharT> result;
|
||||
return EndWriting(result); // copies (since I return a value, not a reference)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* |SetCapacity| is not required to do anything; however, it can be used
|
||||
* as a hint to the implementation to reduce allocations.
|
||||
* |SetCapacity(0)| is a suggestion to discard all associated storage.
|
||||
*/
|
||||
virtual void SetCapacity( PRUint32 ) { }
|
||||
|
||||
/**
|
||||
* |SetLength| is used in two ways:
|
||||
* 1) to |Cut| a suffix of the string;
|
||||
* 2) to prepare to |Append| or move characters around.
|
||||
*
|
||||
* External callers are not allowed to use |SetLength| is this latter capacity.
|
||||
* Should this really be a public operation?
|
||||
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
|
||||
* override the |do_...| routines to not need this facility.
|
||||
*
|
||||
* This distinction makes me think the two different uses should be split into
|
||||
* two distinct functions.
|
||||
*/
|
||||
virtual void SetLength( PRUint32 ) = 0;
|
||||
|
||||
|
||||
void
|
||||
Truncate( PRUint32 aNewLength=0 )
|
||||
{
|
||||
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
|
||||
|
||||
if ( aNewLength < this->Length() )
|
||||
SetLength(aNewLength);
|
||||
}
|
||||
|
||||
|
||||
// PRBool SetCharAt( char_type, index_type ) = 0;
|
||||
|
||||
|
||||
|
||||
// void ToLowerCase();
|
||||
// void ToUpperCase();
|
||||
|
||||
// void StripChars( const CharT* aSet );
|
||||
// void StripChar( ... );
|
||||
// void StripWhitespace();
|
||||
// void ReplaceChar( ... );
|
||||
// void ReplaceSubstring( ... );
|
||||
// void Trim( ... );
|
||||
// void CompressSet( ... );
|
||||
// void CompressWhitespace( ... );
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Assign()|, |operator=()|
|
||||
//
|
||||
|
||||
void Assign( const basic_nsAReadableString<CharT>& aReadable ) { AssignFromReadable(aReadable); }
|
||||
void Assign( const nsPromiseReadable<CharT>& aReadable ) { AssignFromPromise(aReadable); }
|
||||
void Assign( const CharT* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
|
||||
void Assign( const CharT* aPtr, PRUint32 aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
|
||||
void Assign( CharT aChar ) { do_AssignFromElement(aChar); }
|
||||
|
||||
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
|
||||
basic_nsAWritableString<CharT>& operator=( const basic_nsAWritableString<CharT>& aWritable ) { Assign(aWritable); return *this; }
|
||||
|
||||
basic_nsAWritableString<CharT>& operator=( const basic_nsAReadableString<CharT>& aReadable ) { Assign(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( const nsPromiseReadable<CharT>& aReadable ) { Assign(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( const CharT* aPtr ) { Assign(aPtr); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( CharT aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|, |operator+=()|
|
||||
//
|
||||
|
||||
void Append( const basic_nsAReadableString<CharT>& aReadable ) { AppendFromReadable(aReadable); }
|
||||
void Append( const nsPromiseReadable<CharT>& aReadable ) { AppendFromPromise(aReadable); }
|
||||
void Append( const CharT* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
|
||||
void Append( const CharT* aPtr, PRUint32 aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
|
||||
void Append( CharT aChar ) { do_AppendFromElement(aChar); }
|
||||
|
||||
basic_nsAWritableString<CharT>& operator+=( const basic_nsAReadableString<CharT>& aReadable ) { Append(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( const nsPromiseReadable<CharT>& aReadable ) { Append(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( const CharT* aPtr ) { Append(aPtr); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( CharT aChar ) { Append(aChar); return *this; }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The following index based routines need to be recast with iterators.
|
||||
*/
|
||||
|
||||
//
|
||||
// |Insert()|
|
||||
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
|
||||
//
|
||||
|
||||
void Insert( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition ) { InsertFromReadable(aReadable, atPosition); }
|
||||
void Insert( const nsPromiseReadable<CharT>& aReadable, PRUint32 atPosition ) { InsertFromPromise(aReadable, atPosition); }
|
||||
void Insert( const CharT* aPtr, PRUint32 atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
|
||||
void Insert( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
|
||||
void Insert( CharT aChar, PRUint32 atPosition ) { do_InsertFromElement(aChar, atPosition); }
|
||||
|
||||
|
||||
|
||||
virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
|
||||
|
||||
|
||||
|
||||
void Replace( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
|
||||
void Replace( PRUint32 cutStart, PRUint32 cutLength, const nsPromiseReadable<CharT>& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
|
||||
|
||||
private:
|
||||
typedef typename nsCharTraits<CharT>::incompatible_char_type incompatible_char_type;
|
||||
|
||||
// NOT TO BE IMPLEMENTED
|
||||
void operator= ( incompatible_char_type );
|
||||
void Assign ( incompatible_char_type );
|
||||
void operator+= ( incompatible_char_type );
|
||||
void Append ( incompatible_char_type );
|
||||
void Insert ( incompatible_char_type, PRUint32 );
|
||||
|
||||
|
||||
protected:
|
||||
void AssignFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
void AssignFromPromise( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AssignFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AssignFromElementPtr( const CharT* );
|
||||
virtual void do_AssignFromElementPtrLength( const CharT*, PRUint32 );
|
||||
virtual void do_AssignFromElement( CharT );
|
||||
|
||||
void AppendFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
void AppendFromPromise( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AppendFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AppendFromElementPtr( const CharT* );
|
||||
virtual void do_AppendFromElementPtrLength( const CharT*, PRUint32 );
|
||||
virtual void do_AppendFromElement( CharT );
|
||||
|
||||
void InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
void InsertFromPromise( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
virtual void do_InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
virtual void do_InsertFromElementPtr( const CharT*, PRUint32 );
|
||||
virtual void do_InsertFromElementPtrLength( const CharT*, PRUint32, PRUint32 );
|
||||
virtual void do_InsertFromElement( CharT, PRUint32 );
|
||||
|
||||
void ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
void ReplaceFromPromise( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |nsWritingIterator|s
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
void
|
||||
nsWritingIterator<CharT>::normalize_forward()
|
||||
{
|
||||
while ( mPosition == mFragment.mEnd
|
||||
&& mOwningString->GetWritableFragment(mFragment, kNextFragment) )
|
||||
mPosition = mFragment.mStart;
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
void
|
||||
nsWritingIterator<CharT>::normalize_backward()
|
||||
{
|
||||
while ( mPosition == mFragment.mStart
|
||||
&& mOwningString->GetWritableFragment(mFragment, kPrevFragment) )
|
||||
mPosition = mFragment.mEnd;
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
PRBool
|
||||
operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
PRBool
|
||||
operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Assign()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AssignFromReadable( const basic_nsAReadableString<CharT>& rhs )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &rhs )
|
||||
do_AssignFromReadable(rhs);
|
||||
// else, self-assign is a no-op
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AssignFromPromise( const basic_nsAReadableString<CharT>& aReadable )
|
||||
/*
|
||||
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
|
||||
E.g.,
|
||||
|
||||
... writable& w ...
|
||||
... readable& r ...
|
||||
|
||||
w = r + w;
|
||||
|
||||
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
|
||||
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
|
||||
of |r| before being retrieved to be appended.
|
||||
|
||||
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
|
||||
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
|
||||
in the case above, |Insert| could have special behavior with significantly better performance. Since
|
||||
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
|
||||
entire promise. If we measure and this turns out to show up on performance radar, we then have the
|
||||
option to fix either the callers or this mechanism.
|
||||
*/
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_AssignFromReadable(aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
// Note: not exception safe. We need something to manage temporary buffers like this
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_AssignFromElementPtrLength(buffer, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromReadable( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
SetLength(0);
|
||||
SetLength(aReadable.Length());
|
||||
// first setting the length to |0| avoids copying characters only to be overwritten later
|
||||
// in the case where the implementation decides to re-allocate
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElementPtr( const CharT* aPtr )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElementPtrLength( const CharT* aPtr, PRUint32 aLength )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElement( CharT aChar )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralChar<CharT>(aChar));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
|
||||
do_AppendFromReadable(aReadable);
|
||||
else
|
||||
AppendFromPromise(aReadable);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AppendFromPromise( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_AppendFromReadable(aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_AppendFromElementPtrLength(buffer, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
SetLength(oldLength + aReadable.Length());
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElementPtr( const CharT* aChar )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElementPtrLength( const CharT* aChar, PRUint32 aLength )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar, aLength));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElement( CharT aChar )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralChar<CharT>(aChar));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Insert()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
|
||||
do_InsertFromReadable(aReadable, atPosition);
|
||||
else
|
||||
InsertFromPromise(aReadable, atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::InsertFromPromise( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_InsertFromReadable(aReadable, atPosition);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_InsertFromElementPtrLength(buffer, atPosition, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
SetLength(oldLength + aReadable.Length());
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
if ( atPosition < oldLength )
|
||||
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
|
||||
else
|
||||
atPosition = oldLength;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElementPtr( const CharT* aPtr, PRUint32 atPosition )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr), atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElementPtrLength( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength), atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElement( CharT aChar, PRUint32 atPosition )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralChar<CharT>(aChar), atPosition);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Cut()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
|
||||
{
|
||||
PRUint32 myLength = this->Length();
|
||||
cutLength = NS_MIN(cutLength, myLength-cutStart);
|
||||
PRUint32 cutEnd = cutStart + cutLength;
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
if ( cutEnd < myLength )
|
||||
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
|
||||
SetLength(myLength-cutLength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Replace()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReplacement )
|
||||
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
|
||||
else
|
||||
ReplaceFromPromise(cutStart, cutLength, aReplacement);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::ReplaceFromPromise( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_ReplaceFromReadable(cutStart, cutLength, basic_nsLiteralString<CharT>(buffer, length));
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
|
||||
cutStart = NS_MIN(cutStart, oldLength);
|
||||
cutLength = NS_MIN(cutLength, oldLength-cutStart);
|
||||
PRUint32 cutEnd = cutStart + cutLength;
|
||||
|
||||
PRUint32 replacementLength = aReplacement.Length();
|
||||
PRUint32 replacementEnd = cutStart + replacementLength;
|
||||
|
||||
PRUint32 newLength = oldLength - cutLength + replacementLength;
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
if ( cutLength > replacementLength )
|
||||
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
|
||||
SetLength(newLength);
|
||||
if ( cutLength < replacementLength )
|
||||
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
|
||||
|
||||
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
|
||||
}
|
||||
|
||||
|
||||
template <class CharT>
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Mid( basic_nsAWritableString<CharT>& aResult, PRUint32 aStartPos, PRUint32 aLengthToCopy ) const
|
||||
{
|
||||
// If we're just assigning our entire self, give |aResult| the opportunity to share
|
||||
if ( aStartPos == 0 && aLengthToCopy >= Length() )
|
||||
aResult = *this;
|
||||
else
|
||||
aResult = Substring(*this, aStartPos, aLengthToCopy);
|
||||
|
||||
return aResult.Length();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Left( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
|
||||
{
|
||||
return Mid(aResult, 0, aLengthToCopy);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Right( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
|
||||
{
|
||||
PRUint32 myLength = Length();
|
||||
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
|
||||
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Types
|
||||
//
|
||||
|
||||
typedef basic_nsAWritableString<PRUnichar> nsAWritableString;
|
||||
typedef basic_nsAWritableString<char> nsAWritableCString;
|
||||
|
||||
#endif // !defined(nsAWritableString_h___)
|
||||
113
mozilla/string/public/nsAlgorithm.h
Executable file
113
mozilla/string/public/nsAlgorithm.h
Executable file
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsAlgorithm_h___
|
||||
#define nsAlgorithm_h___
|
||||
|
||||
#ifndef nsCharTraits_h___
|
||||
#include "nsCharTraits.h"
|
||||
// for |nsCharSourceTraits|, |nsCharSinkTraits|
|
||||
#endif
|
||||
|
||||
#ifndef prtypes_h___
|
||||
#include "prtypes.h"
|
||||
// for |PRUint32|...
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
const T&
|
||||
NS_MIN( const T& a, const T& b )
|
||||
{
|
||||
return b < a ? b : a;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
const T&
|
||||
NS_MAX( const T& a, const T& b )
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template <class InputIterator, class T>
|
||||
inline
|
||||
PRUint32
|
||||
NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
|
||||
{
|
||||
PRUint32 result = 0;
|
||||
for ( ; first != last; ++first )
|
||||
if ( *first == value )
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class InputIterator, class OutputIterator>
|
||||
inline
|
||||
OutputIterator&
|
||||
copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
|
||||
{
|
||||
typedef nsCharSourceTraits<InputIterator> source_traits;
|
||||
typedef nsCharSinkTraits<OutputIterator> sink_traits;
|
||||
|
||||
while ( first != last )
|
||||
{
|
||||
PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
|
||||
NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
|
||||
source_traits::advance(first, count_copied);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class InputIterator, class OutputIterator>
|
||||
OutputIterator&
|
||||
copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
|
||||
{
|
||||
while ( first != last )
|
||||
{
|
||||
last.normalize_backward();
|
||||
result.normalize_backward();
|
||||
PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
|
||||
if ( first.fragment().mStart == last.fragment().mStart )
|
||||
lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
|
||||
|
||||
NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// XXX Visual C++ can't stomach 'typename' where it rightfully should
|
||||
nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
|
||||
#else
|
||||
nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
|
||||
#endif
|
||||
|
||||
last.advance( -PRInt32(lengthToCopy) );
|
||||
result.advance( -PRInt32(lengthToCopy) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endif // !defined(nsAlgorithm_h___)
|
||||
181
mozilla/string/public/nsBufferHandle.h
Executable file
181
mozilla/string/public/nsBufferHandle.h
Executable file
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsBufferHandle_h___
|
||||
#define nsBufferHandle_h___
|
||||
|
||||
#include <stddef.h>
|
||||
// for |ptrdiff_t|
|
||||
|
||||
#include "prtypes.h"
|
||||
// for |PRBool|
|
||||
|
||||
#include "nsDebug.h"
|
||||
// for |NS_ASSERTION|
|
||||
|
||||
#include "nsMemory.h"
|
||||
// for |nsMemory::Free|
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsBufferHandle
|
||||
{
|
||||
public:
|
||||
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
|
||||
|
||||
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
|
||||
CharT* DataStart() { return mDataStart; }
|
||||
const CharT* DataStart() const { return mDataStart; }
|
||||
|
||||
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
|
||||
CharT* DataEnd() { return mDataEnd; }
|
||||
const CharT* DataEnd() const { return mDataEnd; }
|
||||
|
||||
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
|
||||
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
|
||||
|
||||
protected:
|
||||
CharT* mDataStart;
|
||||
CharT* mDataEnd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsSharedBufferHandle
|
||||
: public nsBufferHandle<CharT>
|
||||
{
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
kIsShared = 1<<31,
|
||||
kIsSingleAllocationWithBuffer = 1<<30,
|
||||
kIsStorageDefinedSeparately = 1<<29,
|
||||
|
||||
kFlagsMask = kIsShared | kIsSingleAllocationWithBuffer | kIsStorageDefinedSeparately,
|
||||
kRefCountMask = ~kFlagsMask
|
||||
};
|
||||
|
||||
public:
|
||||
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
|
||||
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
|
||||
{
|
||||
mFlags |= kIsShared;
|
||||
}
|
||||
|
||||
~nsSharedBufferHandle();
|
||||
|
||||
void
|
||||
AcquireReference() const
|
||||
{
|
||||
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
|
||||
mutable_this->set_refcount( get_refcount()+1 );
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseReference() const
|
||||
{
|
||||
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
|
||||
if ( !mutable_this->set_refcount( get_refcount()-1 ) )
|
||||
delete mutable_this;
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsReferenced() const
|
||||
{
|
||||
return get_refcount() != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRUint32 mFlags;
|
||||
|
||||
PRUint32
|
||||
get_refcount() const
|
||||
{
|
||||
return mFlags & kRefCountMask;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
set_refcount( PRUint32 aNewRefCount )
|
||||
{
|
||||
NS_ASSERTION(aNewRefCount <= kRefCountMask, "aNewRefCount <= kRefCountMask");
|
||||
|
||||
mFlags = (mFlags & kFlagsMask) | aNewRefCount;
|
||||
return aNewRefCount;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// need a name for this
|
||||
template <class CharT>
|
||||
class nsFlexBufferHandle
|
||||
: public nsSharedBufferHandle<CharT>
|
||||
{
|
||||
public:
|
||||
nsFlexBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
|
||||
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
|
||||
mStorageStart(aStorageStart),
|
||||
mStorageEnd(aStorageEnd)
|
||||
{
|
||||
this->mFlags |= this->kIsStorageDefinedSeparately;
|
||||
}
|
||||
|
||||
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
|
||||
CharT* StorageStart() { return mStorageStart; }
|
||||
const CharT* StorageStart() const { return mStorageStart; }
|
||||
|
||||
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
|
||||
CharT* StorageEnd() { return mStorageEnd; }
|
||||
const CharT* StorageEnd() const { return mStorageEnd; }
|
||||
|
||||
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
|
||||
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
|
||||
|
||||
protected:
|
||||
CharT* mStorageStart;
|
||||
CharT* mStorageEnd;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
|
||||
// really don't want this to be |inline|
|
||||
{
|
||||
NS_ASSERTION(!IsReferenced(), "!IsReferenced()");
|
||||
|
||||
if ( !(mFlags & kIsSingleAllocationWithBuffer) )
|
||||
{
|
||||
CharT* string_storage = this->mDataStart;
|
||||
if ( mFlags & kIsStorageDefinedSeparately )
|
||||
string_storage = NS_REINTERPRET_CAST(nsFlexBufferHandle<CharT>*, this)->StorageStart();
|
||||
nsMemory::Free(string_storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // !defined(nsBufferHandle_h___)
|
||||
703
mozilla/string/public/nsCharTraits.h
Normal file
703
mozilla/string/public/nsCharTraits.h
Normal file
@@ -0,0 +1,703 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*/
|
||||
|
||||
#ifndef nsCharTraits_h___
|
||||
#define nsCharTraits_h___
|
||||
|
||||
#include <ctype.h>
|
||||
// for |EOF|, |WEOF|
|
||||
|
||||
#include <string.h>
|
||||
// for |memcpy|, et al
|
||||
|
||||
#ifndef nscore_h___
|
||||
#include "nscore.h"
|
||||
// for |PRUnichar|
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CPP_BOOL
|
||||
typedef bool nsCharTraits_bool;
|
||||
#else
|
||||
typedef PRBool nsCharTraits_bool;
|
||||
#endif
|
||||
|
||||
template <class CharT>
|
||||
struct nsCharTraits
|
||||
{
|
||||
typedef CharT char_type;
|
||||
typedef char incompatible_char_type;
|
||||
|
||||
static
|
||||
void
|
||||
assign( char_type& lhs, const char_type& rhs )
|
||||
{
|
||||
lhs = rhs;
|
||||
}
|
||||
|
||||
|
||||
// integer representation of characters:
|
||||
|
||||
typedef int int_type;
|
||||
|
||||
static
|
||||
char_type
|
||||
to_char_type( const int_type& c )
|
||||
{
|
||||
return char_type(c);
|
||||
}
|
||||
|
||||
static
|
||||
int_type
|
||||
to_int_type( const char_type& c )
|
||||
{
|
||||
return int_type(c);
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq_int_type( const int_type& lhs, const int_type& rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
|
||||
// |char_type| comparisons:
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq( const char_type& lhs, const char_type& rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
lt( const char_type& lhs, const char_type& rhs )
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
|
||||
// operations on s[n] arrays:
|
||||
|
||||
static
|
||||
char_type*
|
||||
copy( char_type* s1, const char_type* s2, size_t n )
|
||||
{
|
||||
char_type* result = s1;
|
||||
while ( n-- )
|
||||
assign(*s1++, *s2++);
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
char_type*
|
||||
move( char_type* s1, const char_type* s2, size_t n )
|
||||
{
|
||||
char_type* result = s1;
|
||||
|
||||
if ( n )
|
||||
{
|
||||
if ( s2 > s1 )
|
||||
copy(s1, s2, n);
|
||||
else
|
||||
{
|
||||
s1 += n;
|
||||
s2 += n;
|
||||
while ( n-- )
|
||||
assign(*--s1, *--s2);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
char_type*
|
||||
assign( char_type* s, size_t n, const char_type& c )
|
||||
{
|
||||
char_type* result = s;
|
||||
while ( n-- )
|
||||
assign(*s++, c);
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
compare( const char_type* s1, const char_type* s2, size_t n )
|
||||
{
|
||||
for ( ; n--; ++s1, ++s2 )
|
||||
{
|
||||
if ( lt(*s1, *s2) )
|
||||
return -1;
|
||||
if ( lt(*s2, *s1) )
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
size_t
|
||||
length( const char_type* s )
|
||||
{
|
||||
size_t result = 0;
|
||||
while ( !eq(*s++, CharT(0)) )
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
const char_type*
|
||||
find( const char_type* s, size_t n, const char_type& c )
|
||||
{
|
||||
while ( n-- )
|
||||
{
|
||||
if ( eq(*s, c) )
|
||||
return s;
|
||||
++s;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// I/O related:
|
||||
|
||||
typedef streamoff off_type;
|
||||
typedef streampos pos_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
static
|
||||
int_type
|
||||
eof()
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
static
|
||||
int_type
|
||||
not_eof( const int_type& c )
|
||||
{
|
||||
return eq_int_type(c, eof()) ? ~eof() : c;
|
||||
}
|
||||
|
||||
// static state_type get_state( pos_type );
|
||||
#endif
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharTraits<char>
|
||||
{
|
||||
typedef char char_type;
|
||||
typedef PRUnichar incompatible_char_type;
|
||||
|
||||
static
|
||||
void
|
||||
assign( char& lhs, char rhs )
|
||||
{
|
||||
lhs = rhs;
|
||||
}
|
||||
|
||||
|
||||
// integer representation of characters:
|
||||
|
||||
typedef int int_type;
|
||||
|
||||
static
|
||||
char
|
||||
to_char_type( int c )
|
||||
{
|
||||
return char(c);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
to_int_type( char c )
|
||||
{
|
||||
return int( NS_STATIC_CAST(unsigned char, c) );
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq_int_type( int lhs, int rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
|
||||
// |char_type| comparisons:
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq( char lhs, char rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
lt( char lhs, char rhs )
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
|
||||
// operations on s[n] arrays:
|
||||
|
||||
static
|
||||
char*
|
||||
move( char* s1, const char* s2, size_t n )
|
||||
{
|
||||
return NS_STATIC_CAST(char*, memmove(s1, s2, n));
|
||||
}
|
||||
|
||||
static
|
||||
char*
|
||||
copy( char* s1, const char* s2, size_t n )
|
||||
{
|
||||
return NS_STATIC_CAST(char*, memcpy(s1, s2, n));
|
||||
}
|
||||
|
||||
static
|
||||
char*
|
||||
assign( char* s, size_t n, char c )
|
||||
{
|
||||
return NS_STATIC_CAST(char*, memset(s, to_int_type(c), n));
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
compare( const char* s1, const char* s2, size_t n )
|
||||
{
|
||||
return memcmp(s1, s2, n);
|
||||
}
|
||||
|
||||
static
|
||||
size_t
|
||||
length( const char* s )
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
find( const char* s, size_t n, char c )
|
||||
{
|
||||
return NS_REINTERPRET_CAST(const char*, memchr(s, to_int_type(c), n));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// I/O related:
|
||||
|
||||
typedef streamoff off_type;
|
||||
typedef streampos pos_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
static
|
||||
int_type
|
||||
eof()
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
not_eof( int c )
|
||||
{
|
||||
return c==eof() ? ~eof() : c;
|
||||
}
|
||||
|
||||
// static state_type get_state( pos_type );
|
||||
#endif
|
||||
};
|
||||
|
||||
#if 0
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharTraits<wchar_t>
|
||||
{
|
||||
typedef wchar_t char_type;
|
||||
|
||||
static
|
||||
void
|
||||
assign( wchar_t& lhs, wchar_t rhs )
|
||||
{
|
||||
lhs = rhs;
|
||||
}
|
||||
|
||||
|
||||
// integer representation of characters:
|
||||
|
||||
typedef wint_t int_type;
|
||||
|
||||
static
|
||||
wchar_t
|
||||
to_char_type( int_type c )
|
||||
{
|
||||
return wchar_t(c);
|
||||
}
|
||||
|
||||
static
|
||||
int_type
|
||||
to_int_type( wchar_t c )
|
||||
{
|
||||
return int_type(c);
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq_int_type( int_type lhs, int_type rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
|
||||
// |char_type| comparisons:
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
eq( wchar_t lhs, wchar_t rhs )
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
static
|
||||
nsCharTraits_bool
|
||||
lt( wchar_t lhs, wchar_t rhs )
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
|
||||
// operations on s[n] arrays:
|
||||
|
||||
static
|
||||
wchar_t*
|
||||
move( wchar_t* s1, const wchar_t* s2, size_t n )
|
||||
{
|
||||
return NS_STATIC_CAST(wchar_t*, wmemmove(s1, s2, n));
|
||||
}
|
||||
|
||||
static
|
||||
wchar_t*
|
||||
copy( wchar_t* s1, const wchar_t* s2, size_t n )
|
||||
{
|
||||
return NS_STATIC_CAST(wchar_t*, wmemcpy(s1, s2, n));
|
||||
}
|
||||
|
||||
static
|
||||
wchar_t*
|
||||
assign( wchar_t* s, size_t n, wchar_t c )
|
||||
{
|
||||
return NS_STATIC_CAST(wchar_t*, wmemset(s, to_int_type(c), n));
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
compare( const wchar_t* s1, const wchar_t* s2, size_t n )
|
||||
{
|
||||
return wmemcmp(s1, s2, n);
|
||||
}
|
||||
|
||||
static
|
||||
size_t
|
||||
length( const wchar_t* s )
|
||||
{
|
||||
return wcslen(s);
|
||||
}
|
||||
|
||||
static
|
||||
const wchar_t*
|
||||
find( const wchar_t* s, size_t n, wchar_t c )
|
||||
{
|
||||
return NS_REINTERPRET_CAST(const wchar_t*, wmemchr(s, to_int_type(c), n));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// I/O related:
|
||||
|
||||
typedef streamoff off_type;
|
||||
typedef streampos pos_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
static
|
||||
int_type
|
||||
eof()
|
||||
{
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
static
|
||||
int_type
|
||||
not_eof( int_type c )
|
||||
{
|
||||
return c==eof() ? ~eof() : c;
|
||||
}
|
||||
|
||||
// static state_type get_state( pos_type );
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template <class InputIterator>
|
||||
struct nsCharSourceTraits
|
||||
{
|
||||
typedef typename InputIterator::difference_type difference_type;
|
||||
|
||||
#if 0
|
||||
static
|
||||
PRUint32
|
||||
distance( const InputIterator& first, const InputIterator& last )
|
||||
{
|
||||
// ...
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const InputIterator& iter )
|
||||
{
|
||||
return iter.size_forward();
|
||||
}
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const InputIterator& first, const InputIterator& last )
|
||||
{
|
||||
return PRUint32(SameFragment(first, last) ? last.get()-first.get() : first.size_forward());
|
||||
}
|
||||
|
||||
static
|
||||
const typename InputIterator::value_type*
|
||||
read( const InputIterator& iter )
|
||||
{
|
||||
return iter.get();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
advance( InputIterator& s, difference_type n )
|
||||
{
|
||||
s.advance(n);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class CharT>
|
||||
struct nsCharSourceTraits<CharT*>
|
||||
{
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
#if 0
|
||||
static
|
||||
PRUint32
|
||||
distance( CharT* first, CharT* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( CharT* s )
|
||||
{
|
||||
return PRUint32(nsCharTraits<CharT>::length(s));
|
||||
// return numeric_limits<PRUint32>::max();
|
||||
}
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( CharT* first, CharT* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
|
||||
static
|
||||
const CharT*
|
||||
read( CharT* s )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
advance( CharT*& s, difference_type n )
|
||||
{
|
||||
s += n;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharSourceTraits<const char*>
|
||||
{
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
#if 0
|
||||
static
|
||||
PRUint32
|
||||
distance( const char* first, const char* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const char* s )
|
||||
{
|
||||
return PRUint32(nsCharTraits<char>::length(s));
|
||||
// return numeric_limits<PRUint32>::max();
|
||||
}
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const char* first, const char* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
|
||||
static
|
||||
const char*
|
||||
read( const char* s )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
advance( const char*& s, difference_type n )
|
||||
{
|
||||
s += n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharSourceTraits<const PRUnichar*>
|
||||
{
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
#if 0
|
||||
static
|
||||
PRUint32
|
||||
distance( const PRUnichar* first, const PRUnichar* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const PRUnichar* s )
|
||||
{
|
||||
return PRUint32(nsCharTraits<PRUnichar>::length(s));
|
||||
// return numeric_limits<PRUint32>::max();
|
||||
}
|
||||
|
||||
static
|
||||
PRUint32
|
||||
readable_distance( const PRUnichar* first, const PRUnichar* last )
|
||||
{
|
||||
return PRUint32(last-first);
|
||||
}
|
||||
|
||||
static
|
||||
const PRUnichar*
|
||||
read( const PRUnichar* s )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
advance( const PRUnichar*& s, difference_type n )
|
||||
{
|
||||
s += n;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template <class OutputIterator>
|
||||
struct nsCharSinkTraits
|
||||
{
|
||||
static
|
||||
PRUint32
|
||||
write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
|
||||
{
|
||||
return iter.write(s, n);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class CharT>
|
||||
struct nsCharSinkTraits<CharT*>
|
||||
{
|
||||
static
|
||||
PRUint32
|
||||
write( CharT*& iter, const CharT* s, PRUint32 n )
|
||||
{
|
||||
nsCharTraits<CharT>::move(iter, s, n);
|
||||
iter += n;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharSinkTraits<char*>
|
||||
{
|
||||
static
|
||||
PRUint32
|
||||
write( char*& iter, const char* s, PRUint32 n )
|
||||
{
|
||||
nsCharTraits<char>::move(iter, s, n);
|
||||
iter += n;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
NS_SPECIALIZE_TEMPLATE
|
||||
struct nsCharSinkTraits<PRUnichar*>
|
||||
{
|
||||
static
|
||||
PRUint32
|
||||
write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
|
||||
{
|
||||
nsCharTraits<PRUnichar>::move(iter, s, n);
|
||||
iter += n;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(nsCharTraits_h___)
|
||||
69
mozilla/string/public/nsFragmentedString.h
Normal file
69
mozilla/string/public/nsFragmentedString.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla XPCOM.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsFragmentedString_h___
|
||||
#define nsFragmentedString_h___
|
||||
|
||||
// WORK IN PROGRESS
|
||||
|
||||
#ifndef nsAWritableString_h___
|
||||
#include "nsAWritableString.h"
|
||||
#endif
|
||||
|
||||
#ifndef nsSharedBufferList_h___
|
||||
#include "nsSharedBufferList.h"
|
||||
#endif
|
||||
|
||||
|
||||
class nsFragmentedString
|
||||
: public basic_nsAWritableString<PRUnichar>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
protected:
|
||||
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
|
||||
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
|
||||
|
||||
public:
|
||||
nsFragmentedString() { }
|
||||
|
||||
virtual PRUint32 Length() const;
|
||||
|
||||
virtual void SetLength( PRUint32 aNewLength );
|
||||
// virtual void SetCapacity( PRUint32 aNewCapacity );
|
||||
|
||||
// virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
|
||||
|
||||
protected:
|
||||
// virtual void do_AssignFromReadable( const basic_nsAReadableString<PRUnichar>& );
|
||||
// virtual void do_AppendFromReadable( const basic_nsAReadableString<PRUnichar>& );
|
||||
// virtual void do_InsertFromReadable( const basic_nsAReadableString<PRUnichar>&, PRUint32 );
|
||||
// virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<PRUnichar>& );
|
||||
|
||||
private:
|
||||
nsSharedBufferList mBufferList;
|
||||
};
|
||||
|
||||
#endif // !defined(nsFragmentedString_h___)
|
||||
93
mozilla/string/public/nsPrintfCString.h
Executable file
93
mozilla/string/public/nsPrintfCString.h
Executable file
@@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Original Author:
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#ifndef nsPrintfCString_h___
|
||||
#define nsPrintfCString_h___
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
|
||||
/**
|
||||
* |nsPrintfCString| lets you use a formated |printf| string as an |nsAReadableCString|.
|
||||
*
|
||||
* myCStr += nsPrintfCString("%f", 13.917);
|
||||
* // ...a general purpose substitute for |AppendFloat|
|
||||
*
|
||||
* For longer patterns, you'll want to use the constructor that takes a length
|
||||
*
|
||||
* nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
|
||||
*
|
||||
* Exceding the default size (which you must specify in the constructor, it is not determined)
|
||||
* causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
|
||||
* cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
|
||||
* This class is intended to be useful for numbers and short
|
||||
* strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
|
||||
* wide version of this class, since wide |printf| is not generally available. That means
|
||||
* to get a wide version of your formatted data, you must, e.g.,
|
||||
*
|
||||
* CopyASCIItoUCS2(nsPrintfCString("%f", 13.917"), myStr);
|
||||
*
|
||||
* That's another good reason to avoid this class for anything but numbers ... as strings can be
|
||||
* much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
|
||||
*/
|
||||
|
||||
class nsPrintfCString
|
||||
: public nsAReadableCString
|
||||
{
|
||||
enum { kLocalBufferSize=15 };
|
||||
// ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
|
||||
// pinkerton suggests 7. We should measure and decide what's appropriate
|
||||
|
||||
|
||||
public:
|
||||
explicit nsPrintfCString( const char* format, ... );
|
||||
nsPrintfCString( size_t n, const char* format, ...);
|
||||
~nsPrintfCString();
|
||||
|
||||
virtual PRUint32 Length() const;
|
||||
|
||||
protected:
|
||||
virtual const char* GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const;
|
||||
// virtual PRBool GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const;
|
||||
|
||||
private:
|
||||
char* mStart;
|
||||
PRUint32 mLength;
|
||||
char mLocalBuffer[ kLocalBufferSize + 1 ];
|
||||
};
|
||||
|
||||
#endif // !defined(nsPrintfCString_h___)
|
||||
60
mozilla/string/public/nsPrivateSharableString.h
Executable file
60
mozilla/string/public/nsPrivateSharableString.h
Executable file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsPrivateSharableString_h___
|
||||
#define nsPrivateSharableString_h___
|
||||
|
||||
#ifndef nsBufferHandle_h___
|
||||
#include "nsBufferHandle.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class is (will be) part of the machinery that makes
|
||||
* most string implementations in this family share their underlying buffers
|
||||
* when convenient. It is _not_ part of the abstract string interface,
|
||||
* though other machinery interested in sharing buffers will know about it.
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsPrivateSharableString
|
||||
{
|
||||
public:
|
||||
virtual const nsBufferHandle<CharT>* GetBufferHandle() const;
|
||||
virtual const nsSharedBufferHandle<CharT>* GetSharedBufferHandle() const;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
const nsSharedBufferHandle<CharT>*
|
||||
nsPrivateSharableString<CharT>::GetSharedBufferHandle() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
const nsBufferHandle<CharT>*
|
||||
nsPrivateSharableString<CharT>::GetBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
#endif // !defined(nsPrivateSharableString_h___)
|
||||
145
mozilla/string/public/nsReadableUtils.h
Executable file
145
mozilla/string/public/nsReadableUtils.h
Executable file
@@ -0,0 +1,145 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
* Johnny Stenbeck <jst@netscape.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsReadableUtils_h___
|
||||
#define nsReadableUtils_h___
|
||||
|
||||
/**
|
||||
* I guess all the routines in this file are all mis-named.
|
||||
* According to our conventions, they should be |NS_xxx|.
|
||||
*/
|
||||
|
||||
#ifndef nsAWritableString_h___
|
||||
#include "nsAWritableString.h"
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
|
||||
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
|
||||
#endif
|
||||
|
||||
|
||||
NS_COM void CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest );
|
||||
NS_COM void CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest );
|
||||
|
||||
/**
|
||||
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
|
||||
*
|
||||
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
|
||||
* Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
|
||||
* This conversion is not well defined; but it reproduces legacy string behavior.
|
||||
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
|
||||
*
|
||||
* @param aSource a 16-bit wide string
|
||||
* @return a new |char| buffer you must free with |nsMemory::Free|.
|
||||
*/
|
||||
NS_COM char* ToNewCString( const nsAReadableString& aSource );
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
|
||||
*
|
||||
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
|
||||
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
|
||||
*
|
||||
* @param aSource an 8-bit wide string
|
||||
* @return a new |char| buffer you must free with |nsMemory::Free|.
|
||||
*/
|
||||
NS_COM char* ToNewCString( const nsAReadableCString& aSource );
|
||||
|
||||
/**
|
||||
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
|
||||
*
|
||||
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
|
||||
* Performs a encoding conversion by converting 16-bit wide characters down to UTF8 encoded 8-bits wide string copying |aSource| to your new buffer.
|
||||
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
|
||||
*
|
||||
* @param aSource a 16-bit wide string
|
||||
* @return a new |char| buffer you must free with |nsMemory::Free|.
|
||||
*/
|
||||
|
||||
NS_COM char* ToNewUTF8String( const nsAReadableString& aSource );
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
|
||||
*
|
||||
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
|
||||
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
|
||||
*
|
||||
* @param aSource a 16-bit wide string
|
||||
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
|
||||
*/
|
||||
NS_COM PRUnichar* ToNewUnicode( const nsAReadableString& aSource );
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
|
||||
*
|
||||
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
|
||||
* Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
|
||||
* This conversion is not well defined; but it reproduces legacy string behavior.
|
||||
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
|
||||
*
|
||||
* @param aSource an 8-bit wide string
|
||||
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
|
||||
*/
|
||||
NS_COM PRUnichar* ToNewUnicode( const nsAReadableCString& aSource );
|
||||
|
||||
/**
|
||||
* Copies |aLength| 16-bit characters from the start of |aSource| to the
|
||||
* |PRUnichar| buffer |aDest|.
|
||||
*
|
||||
* After this operation |aDest| is not null terminated.
|
||||
*
|
||||
* @param aSource a 16-bit wide string
|
||||
* @param aDest a |PRUnichar| buffer
|
||||
* @param aLength the number of 16-bit characters to copy
|
||||
* @return pointer to destination buffer - identical to |aDest|
|
||||
*/
|
||||
NS_COM PRUnichar* CopyUnicodeTo( const nsAReadableString& aSource,
|
||||
PRUnichar* aDest,
|
||||
PRUint32 aLength );
|
||||
|
||||
|
||||
/**
|
||||
* Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
|
||||
*
|
||||
* @param aString a 16-bit wide string to scan
|
||||
*/
|
||||
NS_COM PRBool IsASCII( const nsAReadableString& aString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts case in place in the argument string.
|
||||
*/
|
||||
NS_COM void ToUpperCase( nsAWritableString& );
|
||||
NS_COM void ToUpperCase( nsAWritableCString& );
|
||||
|
||||
NS_COM void ToLowerCase( nsAWritableString& );
|
||||
NS_COM void ToLowerCase( nsAWritableCString& );
|
||||
|
||||
#endif // !defined(nsReadableUtils_h___)
|
||||
163
mozilla/string/public/nsSharedBufferList.h
Executable file
163
mozilla/string/public/nsSharedBufferList.h
Executable file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsSharedBufferList_h___
|
||||
#define nsSharedBufferList_h___
|
||||
|
||||
#ifndef nsBufferHandle_h___
|
||||
#include "nsBufferHandle.h"
|
||||
// for |nsSharedBufferHandle|
|
||||
#endif
|
||||
|
||||
#ifndef nscore_h___
|
||||
#include "nscore.h"
|
||||
// for |PRUnichar|
|
||||
#endif
|
||||
|
||||
#ifndef nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
// for |nsReadingIterator|
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class forms the basis for several multi-fragment string classes, in
|
||||
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
|
||||
*
|
||||
* This class is not templated. It is provided only for |PRUnichar|-based strings.
|
||||
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
|
||||
* or else duplicate this class.
|
||||
*/
|
||||
class nsSharedBufferList
|
||||
{
|
||||
public:
|
||||
|
||||
class Buffer
|
||||
: public nsFlexBufferHandle<PRUnichar>
|
||||
{
|
||||
public:
|
||||
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd, PRBool aIsSingleAllocation=PR_FALSE )
|
||||
: nsFlexBufferHandle<PRUnichar>(aDataStart, aDataEnd, aStorageStart, aStorageEnd)
|
||||
{
|
||||
if ( aIsSingleAllocation )
|
||||
this->mFlags |= this->kIsSingleAllocationWithBuffer;
|
||||
}
|
||||
|
||||
Buffer* mPrev;
|
||||
Buffer* mNext;
|
||||
|
||||
private:
|
||||
// pass-by-value is explicitly denied
|
||||
Buffer( const Buffer& ); // NOT TO BE IMPLEMENTED
|
||||
void operator=( const Buffer& ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
struct Position
|
||||
{
|
||||
Buffer* mBuffer;
|
||||
PRUnichar* mPosInBuffer;
|
||||
|
||||
Position() { }
|
||||
Position( Buffer* aBuffer, PRUnichar* aPosInBuffer ) : mBuffer(aBuffer), mPosInBuffer(aPosInBuffer) { }
|
||||
|
||||
// Position( const Position& ); -- auto-generated copy-constructor OK
|
||||
// Position& operator=( const Position& ); -- auto-generated copy-assignment OK
|
||||
// ~Position(); -- auto-generated destructor OK
|
||||
|
||||
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
|
||||
explicit
|
||||
Position( const nsReadingIterator<PRUnichar>& aIter )
|
||||
: mBuffer( NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier)) ),
|
||||
mPosInBuffer( NS_CONST_CAST(PRUnichar*, aIter.get()) )
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
|
||||
Position&
|
||||
operator=( const nsReadingIterator<PRUnichar>& aIter )
|
||||
{
|
||||
mBuffer = NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier));
|
||||
mPosInBuffer = NS_CONST_CAST(PRUnichar*, aIter.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void PointTo( Buffer* aBuffer, PRUnichar* aPosInBuffer ) { mBuffer=aBuffer; mPosInBuffer=aPosInBuffer; }
|
||||
void PointBefore( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataStart()); }
|
||||
void PointAfter( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataEnd()); }
|
||||
|
||||
// Position( const Position& ); -- automatically generated copy-constructor is OK
|
||||
// Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
nsSharedBufferList( Buffer* aBuffer = 0 )
|
||||
: mFirstBuffer(aBuffer),
|
||||
mLastBuffer(aBuffer),
|
||||
mTotalDataLength(0)
|
||||
{
|
||||
if ( aBuffer )
|
||||
{
|
||||
aBuffer->mPrev = aBuffer->mNext = 0;
|
||||
mTotalDataLength = aBuffer->DataLength();
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~nsSharedBufferList();
|
||||
|
||||
private:
|
||||
// pass-by-value is explicitly denied
|
||||
nsSharedBufferList( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
|
||||
void operator=( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
|
||||
|
||||
public:
|
||||
void LinkBuffer( Buffer*, Buffer*, Buffer* );
|
||||
Buffer* UnlinkBuffer( Buffer* );
|
||||
void SplitBuffer( const Position& );
|
||||
|
||||
static Buffer* NewSingleAllocationBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 );
|
||||
static Buffer* NewWrappingBuffer( PRUnichar*, PRUnichar*, PRUnichar* );
|
||||
|
||||
void DiscardSuffix( PRUint32 );
|
||||
// need other discards: prefix, and by iterator or pointer or something
|
||||
|
||||
Buffer* GetFirstBuffer() { return mFirstBuffer; }
|
||||
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
|
||||
|
||||
Buffer* GetLastBuffer() { return mLastBuffer; }
|
||||
const Buffer* GetLastBuffer() const { return mLastBuffer; }
|
||||
|
||||
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
|
||||
|
||||
protected:
|
||||
void DestroyBuffers();
|
||||
|
||||
protected:
|
||||
Buffer* mFirstBuffer;
|
||||
Buffer* mLastBuffer;
|
||||
ptrdiff_t mTotalDataLength;
|
||||
};
|
||||
|
||||
#endif // !defined(nsSharedBufferList_h___)
|
||||
203
mozilla/string/public/nsSharedString.h
Normal file
203
mozilla/string/public/nsSharedString.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Original Author:
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsSharedString_h___
|
||||
#define nsSharedString_h___
|
||||
|
||||
#ifndef nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
#endif
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsSharedString
|
||||
: public basic_nsAReadableString<CharT>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
public:
|
||||
basic_nsSharedString( const CharT* data, size_t length )
|
||||
: mRefCount(0), mData(data), mLength(length)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
private:
|
||||
~basic_nsSharedString() { } // You can't sub-class me, or make an instance of me on the stack
|
||||
|
||||
// NOT TO BE IMPLEMENTED
|
||||
// we're reference counted, remember. copying and passing by value are wrong
|
||||
// basic_nsSharedString(); // we define at least one constructor, so the default constructor will not be auto-generated. It's wrong to create me with no data anyway
|
||||
basic_nsSharedString( const basic_nsSharedString<CharT>& ); // copy-constructor, the auto generated one would reference somebody elses data
|
||||
void operator=( const basic_nsSharedString<CharT>& ); // copy-assignment operator
|
||||
|
||||
// operator delete?
|
||||
|
||||
public:
|
||||
|
||||
virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const;
|
||||
|
||||
virtual
|
||||
PRUint32
|
||||
Length() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
AddRef() const
|
||||
{
|
||||
return ++mRefCount;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
Release() const
|
||||
{
|
||||
nsrefcnt result = --mRefCount;
|
||||
if ( !mRefCount )
|
||||
{
|
||||
// would have to call my destructor by hand here, if there was anything to destruct
|
||||
operator delete(this); // form of |delete| should always match the |new|
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable nsrefcnt mRefCount;
|
||||
const CharT* mData;
|
||||
size_t mLength;
|
||||
};
|
||||
|
||||
NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsSharedString<CharT>, CharT)
|
||||
|
||||
template <class CharT>
|
||||
const CharT*
|
||||
basic_nsSharedString<CharT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 anOffset ) const
|
||||
{
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mData) + mLength;
|
||||
return aFragment.mStart + anOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsSharedStringPtr
|
||||
{
|
||||
public:
|
||||
// default constructor
|
||||
basic_nsSharedStringPtr() : mRawPtr(0) { }
|
||||
|
||||
// copy-constructor
|
||||
basic_nsSharedStringPtr( const basic_nsSharedStringPtr<CharT>& rhs )
|
||||
: mRawPtr(rhs.mRawPtr)
|
||||
{
|
||||
mRawPtr->AddRef();
|
||||
}
|
||||
|
||||
~basic_nsSharedStringPtr()
|
||||
{
|
||||
if ( mRawPtr )
|
||||
mRawPtr->Release();
|
||||
}
|
||||
|
||||
// copy-assignment operator
|
||||
basic_nsSharedStringPtr<CharT>&
|
||||
operator=( const basic_nsSharedStringPtr<CharT>& );
|
||||
|
||||
basic_nsSharedString<CharT>*
|
||||
operator->() const
|
||||
{
|
||||
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
|
||||
return mRawPtr;
|
||||
}
|
||||
|
||||
basic_nsSharedString<CharT>&
|
||||
operator*() const
|
||||
{
|
||||
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
|
||||
return *mRawPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
const basic_nsSharedString<CharT>* mRawPtr;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
basic_nsSharedStringPtr<CharT>&
|
||||
basic_nsSharedStringPtr<CharT>::operator=( const basic_nsSharedStringPtr<CharT>& rhs )
|
||||
// Not |inline|
|
||||
{
|
||||
if ( rhs.mRawPtr )
|
||||
rhs.mRawPtr->AddRef();
|
||||
basic_nsSharedString<CharT>* oldPtr = mRawPtr;
|
||||
mRawPtr = rhs.mRawPtr;
|
||||
if ( oldPtr )
|
||||
oldPtr->Release();
|
||||
}
|
||||
|
||||
|
||||
template <class CharT>
|
||||
basic_nsSharedString<CharT>*
|
||||
new_nsSharedString( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
size_t object_size = ((sizeof(basic_nsSharedString<CharT>) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
|
||||
size_t string_length = aReadable.Length();
|
||||
size_t string_size = string_length * sizeof(CharT);
|
||||
|
||||
void* object_ptr = operator new(object_size + string_size);
|
||||
if ( object_ptr )
|
||||
{
|
||||
typedef CharT* CharT_ptr;
|
||||
CharT* string_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = string_ptr;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
return new (object_ptr) basic_nsSharedString<CharT>(string_ptr, string_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef basic_nsSharedString<PRUnichar> nsSharedString;
|
||||
typedef basic_nsSharedString<char> nsSharedCString;
|
||||
|
||||
typedef basic_nsSharedStringPtr<PRUnichar> nsSharedStringPtr;
|
||||
typedef basic_nsSharedStringPtr<char> nsSharedCStringPtr;
|
||||
|
||||
|
||||
#endif // !defined(nsSharedString_h___)
|
||||
135
mozilla/string/public/nsSlidingString.h
Executable file
135
mozilla/string/public/nsSlidingString.h
Executable file
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef nsSlidingString_h___
|
||||
#define nsSlidingString_h___
|
||||
|
||||
#include "nsAReadableString.h"
|
||||
#include "nsSharedBufferList.h"
|
||||
|
||||
|
||||
/**
|
||||
* Maintains the sequence from the prev-most referenced buffer to the last buffer.
|
||||
* As prev-most buffers become un-referenced, they are unlinked from the list
|
||||
* and destroyed.
|
||||
*
|
||||
* One or more |nsSlidingSubstring|s may reference into the list. Each |nsSlidingSubstring|
|
||||
* holds a reference into the prev-most buffer intersecting the
|
||||
* substring it describes. The destructor of a |nsSlidingSubstring| releases this
|
||||
* reference, allowing the buffer list to destroy the contiguous prefix of
|
||||
* unreferenced buffers.
|
||||
*
|
||||
* A single instance of |nsSlidingString| may reference this list.
|
||||
* Through that interface, new data can be appended onto the next-most end
|
||||
* of the list. |nsSlidingString| also the client to advance its starting point.
|
||||
*
|
||||
*/
|
||||
class nsSlidingSharedBufferList
|
||||
: public nsSharedBufferList
|
||||
{
|
||||
public:
|
||||
nsSlidingSharedBufferList( Buffer* aBuffer ) : nsSharedBufferList(aBuffer), mRefCount(0) { }
|
||||
|
||||
void AcquireReference() { ++mRefCount; }
|
||||
void ReleaseReference() { if ( !--mRefCount ) delete this; }
|
||||
|
||||
void DiscardUnreferencedPrefix( Buffer* );
|
||||
|
||||
private:
|
||||
PRUint32 mRefCount;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* a substring over a buffer list, this
|
||||
*/
|
||||
class nsSlidingSubstring
|
||||
: public nsPromiseReadable<PRUnichar>
|
||||
{
|
||||
public:
|
||||
typedef nsSlidingSharedBufferList::Buffer Buffer;
|
||||
typedef nsSlidingSharedBufferList::Position Position;
|
||||
|
||||
nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor
|
||||
nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
|
||||
~nsSlidingSubstring();
|
||||
|
||||
virtual PRUint32 Length() const { return mLength; }
|
||||
|
||||
protected:
|
||||
nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList );
|
||||
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
|
||||
|
||||
private:
|
||||
// can't assign into me, I'm a read-only reference
|
||||
void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED
|
||||
|
||||
protected:
|
||||
Position mStart;
|
||||
Position mEnd;
|
||||
nsSlidingSharedBufferList& mBufferList;
|
||||
PRUint32 mLength;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class.
|
||||
*
|
||||
*/
|
||||
class nsSlidingString
|
||||
: public nsSlidingSubstring
|
||||
{
|
||||
public:
|
||||
nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
|
||||
// ...created by consuming ownership of a buffer ... |aStorageStart| must point to something
|
||||
// that it will be OK for the slidking string to call |nsMemory::Free| on
|
||||
|
||||
// you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done
|
||||
void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
|
||||
|
||||
// void Append( ... ); do you want some |Append|s that copy the supplied data?
|
||||
|
||||
void DiscardPrefix( const nsReadingIterator<PRUnichar>& );
|
||||
// any other way you want to do this?
|
||||
|
||||
private:
|
||||
nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
|
||||
void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
// this (or something similar) is what should appear in the parser, I think
|
||||
#include "nsSlidingString.h"
|
||||
|
||||
typedef nsSlidingString nsParserString;
|
||||
typedef nsSlidingSubstring nsParserToken;
|
||||
#endif
|
||||
|
||||
#endif // !defined(nsSlidingString_h___)
|
||||
162
mozilla/string/src/nsFragmentedString.cpp
Executable file
162
mozilla/string/src/nsFragmentedString.cpp
Executable file
@@ -0,0 +1,162 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla XPCOM.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Original Author:
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsFragmentedString.h"
|
||||
|
||||
|
||||
const PRUnichar*
|
||||
nsFragmentedString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
|
||||
{
|
||||
const nsSharedBufferList::Buffer* buffer = 0;
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kPrevFragment:
|
||||
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
|
||||
break;
|
||||
|
||||
case kFirstFragment:
|
||||
buffer = mBufferList.GetFirstBuffer();
|
||||
break;
|
||||
|
||||
case kLastFragment:
|
||||
buffer = mBufferList.GetLastBuffer();
|
||||
break;
|
||||
|
||||
case kNextFragment:
|
||||
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
|
||||
break;
|
||||
|
||||
case kFragmentAt:
|
||||
// ...work...
|
||||
break;
|
||||
}
|
||||
|
||||
if ( buffer )
|
||||
{
|
||||
aFragment.mStart = buffer->DataStart();
|
||||
aFragment.mEnd = buffer->DataEnd();
|
||||
aFragment.mFragmentIdentifier = buffer;
|
||||
return aFragment.mStart + aOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PRUnichar*
|
||||
nsFragmentedString::GetWritableFragment( nsWritableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
|
||||
{
|
||||
nsSharedBufferList::Buffer* buffer = 0;
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kPrevFragment:
|
||||
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
|
||||
break;
|
||||
|
||||
case kFirstFragment:
|
||||
buffer = mBufferList.GetFirstBuffer();
|
||||
break;
|
||||
|
||||
case kLastFragment:
|
||||
buffer = mBufferList.GetLastBuffer();
|
||||
break;
|
||||
|
||||
case kNextFragment:
|
||||
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
|
||||
break;
|
||||
|
||||
case kFragmentAt:
|
||||
// ...work...
|
||||
break;
|
||||
}
|
||||
|
||||
if ( buffer )
|
||||
{
|
||||
aFragment.mStart = buffer->DataStart();
|
||||
aFragment.mEnd = buffer->DataEnd();
|
||||
aFragment.mFragmentIdentifier = buffer;
|
||||
return aFragment.mStart + aOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ...
|
||||
*/
|
||||
PRUint32
|
||||
nsFragmentedString::Length() const
|
||||
{
|
||||
return PRUint32(mBufferList.GetDataLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* |SetLength|
|
||||
*/
|
||||
void
|
||||
nsFragmentedString::SetLength( PRUint32 aNewLength )
|
||||
{
|
||||
// according to the current interpretation of |SetLength|,
|
||||
// cut off characters from the end, or else add unitialized space to fill
|
||||
|
||||
if ( aNewLength < mBufferList.GetDataLength() )
|
||||
{
|
||||
// if ( aNewLength )
|
||||
mBufferList.DiscardSuffix(mBufferList.GetDataLength()-aNewLength);
|
||||
// else
|
||||
// mBufferList.DestroyBuffers();
|
||||
}
|
||||
|
||||
// temporarily... eliminate as soon as our munging routines don't need this form of |SetLength|
|
||||
else if ( aNewLength > mBufferList.GetDataLength() )
|
||||
{
|
||||
size_t empty_space_to_add = aNewLength - mBufferList.GetDataLength();
|
||||
nsSharedBufferList::Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(0, 0, empty_space_to_add);
|
||||
new_buffer->DataEnd(new_buffer->DataStart()+empty_space_to_add);
|
||||
mBufferList.LinkBuffer(mBufferList.GetLastBuffer(), new_buffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* |SetCapacity|.
|
||||
*
|
||||
* If a client tries to increase the capacity of multi-fragment string, perhaps a single
|
||||
* empty fragment of the appropriate size should be appended.
|
||||
*/
|
||||
void
|
||||
nsFragmentedString::SetCapacity( PRUint32 aNewCapacity )
|
||||
{
|
||||
if ( !aNewCapacity )
|
||||
{
|
||||
// |SetCapacity(0)| is special and means ``release all storage''.
|
||||
}
|
||||
else if ( aNewCapacity > ... )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
135
mozilla/string/src/nsPrintfCString.cpp
Executable file
135
mozilla/string/src/nsPrintfCString.cpp
Executable file
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Original Author:
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU General Public License Version 2 or later (the
|
||||
* "GPL"), in which case the provisions of the GPL are applicable
|
||||
* instead of those above. If you wish to allow use of your
|
||||
* version of this file only under the terms of the GPL and not to
|
||||
* allow others to use your version of this file under the MPL,
|
||||
* indicate your decision by deleting the provisions above and
|
||||
* replace them with the notice and other provisions required by
|
||||
* the GPL. If you do not delete the provisions above, a recipient
|
||||
* may use your version of this file under either the MPL or the
|
||||
* GPL.
|
||||
*/
|
||||
|
||||
#include "nsPrintfCString.h"
|
||||
#include <stdarg.h>
|
||||
#include "prprf.h"
|
||||
|
||||
|
||||
nsPrintfCString::nsPrintfCString( const char* format, ... )
|
||||
: mStart(mLocalBuffer),
|
||||
mLength(0)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
size_t logical_capacity = kLocalBufferSize;
|
||||
size_t physical_capacity = logical_capacity + 1;
|
||||
|
||||
va_start(ap, format);
|
||||
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
nsPrintfCString::nsPrintfCString( size_t n, const char* format, ... )
|
||||
: mStart(mLocalBuffer),
|
||||
mLength(0)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
// make sure there's at least |n| space
|
||||
size_t logical_capacity = kLocalBufferSize;
|
||||
if ( n > logical_capacity )
|
||||
{
|
||||
char* nonlocal_buffer = new char[n];
|
||||
|
||||
// if we got something, use it
|
||||
if ( nonlocal_buffer )
|
||||
{
|
||||
mStart = nonlocal_buffer;
|
||||
logical_capacity = n;
|
||||
}
|
||||
// else, it's the error case ... we'll use what space we have
|
||||
// (since we can't throw)
|
||||
}
|
||||
size_t physical_capacity = logical_capacity + 1;
|
||||
|
||||
va_start(ap, format);
|
||||
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
nsPrintfCString::~nsPrintfCString()
|
||||
{
|
||||
if ( mStart != mLocalBuffer )
|
||||
delete [] mStart;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsPrintfCString::Length() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const
|
||||
{
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
aFragment.mFragmentIdentifier = this;
|
||||
// fall through
|
||||
case kThisFragment:
|
||||
aFragment.mStart = mStart;
|
||||
aFragment.mEnd = mStart + mLength;
|
||||
return PR_TRUE;
|
||||
|
||||
default:
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
const char*
|
||||
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
|
||||
{
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mStart) + mLength;
|
||||
return mStart + aOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
343
mozilla/string/src/nsReadableUtils.cpp
Executable file
343
mozilla/string/src/nsReadableUtils.cpp
Executable file
@@ -0,0 +1,343 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*/
|
||||
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
|
||||
template <class CharT> class CalculateLength
|
||||
{
|
||||
public:
|
||||
typedef CharT value_type;
|
||||
|
||||
CalculateLength() : mDistance(0) { }
|
||||
size_t GetDistance() const { return mDistance; }
|
||||
|
||||
PRUint32 write( const CharT*, PRUint32 N )
|
||||
{ mDistance += N; return N; }
|
||||
private:
|
||||
size_t mDistance;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
size_t
|
||||
Distance_Impl( const nsReadingIterator<CharT>& aStart,
|
||||
const nsReadingIterator<CharT>& aEnd )
|
||||
{
|
||||
CalculateLength<CharT> sink;
|
||||
nsReadingIterator<CharT> fromBegin(aStart);
|
||||
copy_string(fromBegin, aEnd, sink);
|
||||
return sink.GetDistance();
|
||||
}
|
||||
|
||||
NS_COM
|
||||
size_t
|
||||
Distance( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
|
||||
{
|
||||
return Distance_Impl(aStart, aEnd);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
size_t
|
||||
Distance( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
|
||||
{
|
||||
return Distance_Impl(aStart, aEnd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A character sink that performs a |reinterpret_cast| style conversion between character types.
|
||||
*/
|
||||
template <class FromCharT, class ToCharT>
|
||||
class LossyConvertEncoding
|
||||
{
|
||||
public:
|
||||
typedef FromCharT value_type;
|
||||
|
||||
typedef FromCharT input_type;
|
||||
typedef ToCharT output_type;
|
||||
|
||||
public:
|
||||
LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { }
|
||||
|
||||
PRUint32
|
||||
write( const input_type* aSource, PRUint32 aSourceLength )
|
||||
{
|
||||
const input_type* done_writing = aSource + aSourceLength;
|
||||
while ( aSource < done_writing )
|
||||
*mDestination++ = (output_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior
|
||||
return aSourceLength;
|
||||
}
|
||||
|
||||
void
|
||||
write_terminator()
|
||||
{
|
||||
*mDestination = output_type(0);
|
||||
}
|
||||
|
||||
private:
|
||||
output_type* mDestination;
|
||||
};
|
||||
|
||||
|
||||
NS_COM
|
||||
void
|
||||
CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest )
|
||||
{
|
||||
// right now, this won't work on multi-fragment destinations
|
||||
aDest.SetLength(aSource.Length());
|
||||
|
||||
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
|
||||
|
||||
nsWritingIterator<char> toBegin;
|
||||
LossyConvertEncoding<PRUnichar, char> converter(aDest.BeginWriting(toBegin).get());
|
||||
|
||||
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
void
|
||||
CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest )
|
||||
{
|
||||
// right now, this won't work on multi-fragment destinations
|
||||
aDest.SetLength(aSource.Length());
|
||||
|
||||
nsReadingIterator<char> fromBegin, fromEnd;
|
||||
|
||||
nsWritingIterator<PRUnichar> toBegin;
|
||||
LossyConvertEncoding<char, PRUnichar> converter(aDest.BeginWriting(toBegin).get());
|
||||
|
||||
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
|
||||
*
|
||||
* @param aSource an string you will eventually be making a copy of
|
||||
* @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
|
||||
*
|
||||
*/
|
||||
template <class FromCharT, class ToCharT>
|
||||
inline
|
||||
ToCharT*
|
||||
AllocateStringCopy( const basic_nsAReadableString<FromCharT>& aSource, ToCharT* )
|
||||
{
|
||||
return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
|
||||
}
|
||||
|
||||
|
||||
NS_COM
|
||||
char*
|
||||
ToNewCString( const nsAReadableString& aSource )
|
||||
{
|
||||
char* result = AllocateStringCopy(aSource, (char*)0);
|
||||
|
||||
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
|
||||
LossyConvertEncoding<PRUnichar, char> converter(result);
|
||||
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
char*
|
||||
ToNewUTF8String( const nsAReadableString& aSource )
|
||||
{
|
||||
NS_ConvertUCS2toUTF8 temp(aSource);
|
||||
|
||||
char* result;
|
||||
if (temp.mOwnsBuffer) {
|
||||
// We allocated. Trick the string into not freeing its buffer to
|
||||
// avoid an extra allocation.
|
||||
result = temp.mStr;
|
||||
|
||||
temp.mStr=0;
|
||||
temp.mOwnsBuffer = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
// We didn't allocate a buffer, so we need to copy it out of the
|
||||
// nsCAutoString's storage.
|
||||
result = nsCRT::strdup(temp.mStr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
char*
|
||||
ToNewCString( const nsAReadableCString& aSource )
|
||||
{
|
||||
// no conversion needed, just allocate a buffer of the correct length and copy into it
|
||||
|
||||
char* result = AllocateStringCopy(aSource, (char*)0);
|
||||
|
||||
nsReadingIterator<char> fromBegin, fromEnd;
|
||||
char* toBegin = result;
|
||||
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRUnichar*
|
||||
ToNewUnicode( const nsAReadableString& aSource )
|
||||
{
|
||||
// no conversion needed, just allocate a buffer of the correct length and copy into it
|
||||
|
||||
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
|
||||
|
||||
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
|
||||
PRUnichar* toBegin = result;
|
||||
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRUnichar*
|
||||
ToNewUnicode( const nsAReadableCString& aSource )
|
||||
{
|
||||
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
|
||||
|
||||
nsReadingIterator<char> fromBegin, fromEnd;
|
||||
LossyConvertEncoding<char, PRUnichar> converter(result);
|
||||
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRUnichar*
|
||||
CopyUnicodeTo( const nsAReadableString& aSource, PRUnichar* aDest, PRUint32 aLength )
|
||||
{
|
||||
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
|
||||
PRUnichar* toBegin = aDest;
|
||||
copy_string(aSource.BeginReading(fromBegin), aSource.BeginReading(fromEnd).advance( PRInt32(aLength) ), toBegin);
|
||||
return aDest;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRBool
|
||||
IsASCII( const nsAReadableString& aString )
|
||||
{
|
||||
static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
|
||||
|
||||
|
||||
// Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
|
||||
|
||||
nsReadingIterator<PRUnichar> done_reading;
|
||||
aString.EndReading(done_reading);
|
||||
|
||||
// for each chunk of |aString|...
|
||||
PRUint32 fragmentLength = 0;
|
||||
nsReadingIterator<PRUnichar> iter;
|
||||
for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
|
||||
{
|
||||
fragmentLength = PRUint32(iter.size_forward());
|
||||
const PRUnichar* c = iter.get();
|
||||
const PRUnichar* fragmentEnd = c + fragmentLength;
|
||||
|
||||
// for each character in this chunk...
|
||||
while ( c < fragmentEnd )
|
||||
if ( *c++ & NOT_ASCII )
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A character sink for case conversion.
|
||||
*/
|
||||
template <class CharT>
|
||||
class ConvertToUpperCase
|
||||
{
|
||||
public:
|
||||
typedef CharT value_type;
|
||||
|
||||
PRUint32
|
||||
write( const CharT* aSource, PRUint32 aSourceLength )
|
||||
{
|
||||
for ( int i=0; i<aSourceLength; ++i )
|
||||
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToUpper(aSource[i]);
|
||||
return aSourceLength;
|
||||
}
|
||||
};
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToUpperCase( nsAWritableString& aString )
|
||||
{
|
||||
nsAWritableString::iterator fromBegin, fromEnd;
|
||||
ConvertToUpperCase<PRUnichar> converter;
|
||||
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToUpperCase( nsAWritableCString& aCString )
|
||||
{
|
||||
nsAWritableCString::iterator fromBegin, fromEnd;
|
||||
ConvertToUpperCase<char> converter;
|
||||
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A character sink for case conversion.
|
||||
*/
|
||||
template <class CharT>
|
||||
class ConvertToLowerCase
|
||||
{
|
||||
public:
|
||||
typedef CharT value_type;
|
||||
|
||||
PRUint32
|
||||
write( const CharT* aSource, PRUint32 aSourceLength )
|
||||
{
|
||||
for ( int i=0; i<aSourceLength; ++i )
|
||||
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToLower(aSource[i]);
|
||||
return aSourceLength;
|
||||
}
|
||||
};
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToLowerCase( nsAWritableString& aString )
|
||||
{
|
||||
nsAWritableString::iterator fromBegin, fromEnd;
|
||||
ConvertToLowerCase<PRUnichar> converter;
|
||||
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToLowerCase( nsAWritableCString& aCString )
|
||||
{
|
||||
nsAWritableCString::iterator fromBegin, fromEnd;
|
||||
ConvertToLowerCase<char> converter;
|
||||
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
186
mozilla/string/src/nsSharedBufferList.cpp
Executable file
186
mozilla/string/src/nsSharedBufferList.cpp
Executable file
@@ -0,0 +1,186 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsSharedBufferList.h"
|
||||
#include "nsAlgorithm.h"
|
||||
// for |copy_string|
|
||||
#include <new.h>
|
||||
|
||||
|
||||
void
|
||||
nsSharedBufferList::DestroyBuffers()
|
||||
{
|
||||
// destroy the entire list of buffers, without bothering to manage their links
|
||||
Buffer* next_buffer;
|
||||
for ( Buffer* cur_buffer=mFirstBuffer; cur_buffer; cur_buffer=next_buffer )
|
||||
{
|
||||
next_buffer = cur_buffer->mNext;
|
||||
operator delete(cur_buffer);
|
||||
}
|
||||
mFirstBuffer = mLastBuffer = 0;
|
||||
mTotalDataLength = 0;
|
||||
}
|
||||
|
||||
nsSharedBufferList::~nsSharedBufferList()
|
||||
{
|
||||
DestroyBuffers();
|
||||
}
|
||||
|
||||
|
||||
nsSharedBufferList::Buffer*
|
||||
nsSharedBufferList::NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
|
||||
{
|
||||
size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
|
||||
PRUint32 buffer_length = aDataLength + aAdditionalSpace;
|
||||
size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar);
|
||||
|
||||
void* object_ptr = operator new(object_size + buffer_size);
|
||||
if ( object_ptr )
|
||||
{
|
||||
typedef PRUnichar* PRUnichar_ptr;
|
||||
PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
|
||||
if ( aDataLength )
|
||||
{
|
||||
PRUnichar* toBegin = buffer_ptr;
|
||||
copy_string(aData, aData+aDataLength, toBegin);
|
||||
}
|
||||
return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length, PR_TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsSharedBufferList::Buffer*
|
||||
nsSharedBufferList::NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
|
||||
{
|
||||
return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer )
|
||||
{
|
||||
NS_ASSERTION(aNewBuffer, "aNewBuffer");
|
||||
NS_ASSERTION(aPrevBuffer || mFirstBuffer == aNextBuffer, "aPrevBuffer || mFirstBuffer == aNextBuffer");
|
||||
NS_ASSERTION(!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer, "!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer");
|
||||
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
|
||||
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
|
||||
|
||||
if ( (aNewBuffer->mPrev = aPrevBuffer) )
|
||||
aPrevBuffer->mNext = aNewBuffer;
|
||||
else
|
||||
mFirstBuffer = aNewBuffer;
|
||||
|
||||
if ( (aNewBuffer->mNext = aNextBuffer) )
|
||||
aNextBuffer->mPrev = aNewBuffer;
|
||||
else
|
||||
mLastBuffer = aNewBuffer;
|
||||
|
||||
mTotalDataLength += aNewBuffer->DataLength();
|
||||
}
|
||||
|
||||
void
|
||||
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition )
|
||||
{
|
||||
Buffer* bufferToSplit = aSplitPosition.mBuffer;
|
||||
|
||||
NS_ASSERTION(bufferToSplit, "bufferToSplit");
|
||||
|
||||
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
|
||||
|
||||
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
|
||||
|
||||
if ( (bufferToSplit->DataLength() >> 1) > splitOffset )
|
||||
{
|
||||
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
|
||||
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
|
||||
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
|
||||
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
|
||||
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsSharedBufferList::Buffer*
|
||||
nsSharedBufferList::UnlinkBuffer( Buffer* aBufferToUnlink )
|
||||
{
|
||||
NS_ASSERTION(aBufferToUnlink, "aBufferToUnlink");
|
||||
|
||||
Buffer* prev_buffer = aBufferToUnlink->mPrev;
|
||||
Buffer* next_buffer = aBufferToUnlink->mNext;
|
||||
|
||||
if ( prev_buffer )
|
||||
prev_buffer->mNext = next_buffer;
|
||||
else
|
||||
mFirstBuffer = next_buffer;
|
||||
|
||||
if ( next_buffer )
|
||||
next_buffer->mPrev = prev_buffer;
|
||||
else
|
||||
mLastBuffer = prev_buffer;
|
||||
|
||||
mTotalDataLength -= aBufferToUnlink->DataLength();
|
||||
|
||||
return aBufferToUnlink;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsSharedBufferList::DiscardSuffix( PRUint32 /* aLengthToDiscard */ )
|
||||
{
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
template <class CharT>
|
||||
void
|
||||
nsChunkList<CharT>::CutTrailingData( PRUint32 aLengthToCut )
|
||||
{
|
||||
Chunk* chunk = mLastChunk;
|
||||
while ( chunk && aLengthToCut )
|
||||
{
|
||||
Chunk* prev_chunk = chunk->mPrev;
|
||||
if ( aLengthToCut < chunk->mDataLength )
|
||||
{
|
||||
chunk->mDataLength -= aLengthToCut;
|
||||
aLengthToCut = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveChunk(chunk);
|
||||
aLengthToCut -= chunk->mDataLength;
|
||||
operator delete(chunk);
|
||||
}
|
||||
|
||||
chunk = prev_chunk;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
180
mozilla/string/src/nsSlidingString.cpp
Executable file
180
mozilla/string/src/nsSlidingString.cpp
Executable file
@@ -0,0 +1,180 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Mozilla strings.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org> (original author)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsSlidingString.h"
|
||||
|
||||
void
|
||||
nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer )
|
||||
{
|
||||
if ( aRecentlyReleasedBuffer == mFirstBuffer )
|
||||
{
|
||||
while ( mFirstBuffer && !mFirstBuffer->IsReferenced() )
|
||||
delete UnlinkBuffer(mFirstBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ptrdiff_t Distance( const nsSharedBufferList::Position&, const nsSharedBufferList::Position& );
|
||||
|
||||
ptrdiff_t
|
||||
Distance( const nsSharedBufferList::Position& aStart, const nsSharedBufferList::Position& aEnd )
|
||||
{
|
||||
ptrdiff_t result = 0;
|
||||
if ( aStart.mBuffer == aEnd.mBuffer )
|
||||
result = aEnd.mPosInBuffer - aStart.mPosInBuffer;
|
||||
else
|
||||
{
|
||||
result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer;
|
||||
for ( nsSharedBufferList::Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext )
|
||||
result += b->DataLength();
|
||||
result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString )
|
||||
: mStart(aString.mStart),
|
||||
mEnd(aString.mEnd),
|
||||
mBufferList(aString.mBufferList),
|
||||
mLength(aString.mLength)
|
||||
{
|
||||
mBufferList.AcquireReference();
|
||||
mStart.mBuffer->AcquireReference();
|
||||
}
|
||||
|
||||
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
|
||||
: mStart(aStart),
|
||||
mEnd(aEnd),
|
||||
mBufferList(aString.mBufferList),
|
||||
mLength(PRUint32(Distance(mStart, mEnd)))
|
||||
{
|
||||
mBufferList.AcquireReference();
|
||||
mStart.mBuffer->AcquireReference();
|
||||
}
|
||||
|
||||
nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList )
|
||||
: mBufferList(aBufferList)
|
||||
{
|
||||
mBufferList.AcquireReference();
|
||||
|
||||
mStart.PointBefore(mBufferList.GetFirstBuffer());
|
||||
mStart.mBuffer->AcquireReference();
|
||||
|
||||
mEnd.PointAfter(mBufferList.GetLastBuffer());
|
||||
mLength = PRUint32(Distance(mStart, mEnd));
|
||||
}
|
||||
|
||||
nsSlidingSubstring::~nsSlidingSubstring()
|
||||
{
|
||||
mStart.mBuffer->ReleaseReference();
|
||||
mBufferList.DiscardUnreferencedPrefix(mStart.mBuffer);
|
||||
mBufferList.ReleaseReference();
|
||||
}
|
||||
|
||||
const PRUnichar*
|
||||
nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
|
||||
{
|
||||
const Buffer* result_buffer = 0;
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kPrevFragment:
|
||||
{
|
||||
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
|
||||
if ( current_buffer != mStart.mBuffer )
|
||||
result_buffer = current_buffer->mPrev;
|
||||
}
|
||||
break;
|
||||
|
||||
case kFirstFragment:
|
||||
result_buffer = mStart.mBuffer;
|
||||
break;
|
||||
|
||||
case kLastFragment:
|
||||
result_buffer = mEnd.mBuffer;
|
||||
break;
|
||||
|
||||
case kNextFragment:
|
||||
{
|
||||
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
|
||||
if ( current_buffer != mEnd.mBuffer )
|
||||
result_buffer = current_buffer->mNext;
|
||||
}
|
||||
break;
|
||||
|
||||
case kFragmentAt:
|
||||
// ...work...
|
||||
break;
|
||||
}
|
||||
|
||||
if ( result_buffer )
|
||||
{
|
||||
if ( result_buffer == mStart.mBuffer )
|
||||
aFragment.mStart = mStart.mPosInBuffer;
|
||||
else
|
||||
aFragment.mStart = result_buffer->DataStart();
|
||||
|
||||
if ( result_buffer == mEnd.mBuffer )
|
||||
aFragment.mEnd = mEnd.mPosInBuffer;
|
||||
else
|
||||
aFragment.mEnd = result_buffer->DataEnd();
|
||||
|
||||
aFragment.mFragmentIdentifier = result_buffer;
|
||||
return aFragment.mStart + aOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
|
||||
: nsSlidingSubstring(*(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd))))
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
void
|
||||
nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
|
||||
{
|
||||
Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd);
|
||||
Buffer* old_last_buffer = mBufferList.GetLastBuffer();
|
||||
mBufferList.LinkBuffer(old_last_buffer, new_buffer, 0);
|
||||
mLength += new_buffer->DataLength();
|
||||
|
||||
mEnd.PointAfter(new_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter )
|
||||
{
|
||||
Position old_start(mStart);
|
||||
mStart = aIter;
|
||||
mLength -= Distance(old_start, mStart);
|
||||
|
||||
mStart.mBuffer->AcquireReference();
|
||||
old_start.mBuffer->ReleaseReference();
|
||||
|
||||
mBufferList.DiscardUnreferencedPrefix(old_start.mBuffer);
|
||||
}
|
||||
746
mozilla/tools/trace-malloc/bloatblame.c
Normal file
746
mozilla/tools/trace-malloc/bloatblame.c
Normal file
@@ -0,0 +1,746 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is nsTraceMalloc.c/bloatblame.c code, released
|
||||
* April 19, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich, 14-April-2000
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the MPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the MPL or the GPL.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#else
|
||||
extern int getopt(int argc, char *const *argv, const char *shortopts);
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include "prtypes.h"
|
||||
#include "prlog.h"
|
||||
#include "prprf.h"
|
||||
#include "plhash.h"
|
||||
#include "nsTraceMalloc.h"
|
||||
#include "tmreader.h"
|
||||
|
||||
static char *program;
|
||||
static int sort_by_direct = 0;
|
||||
static int js_mode = 0;
|
||||
static int do_tree_dump = 0;
|
||||
static int unified_output = 0;
|
||||
static char *function_dump = NULL;
|
||||
static uint32 min_subtotal = 0;
|
||||
|
||||
static void compute_callsite_totals(tmcallsite *site)
|
||||
{
|
||||
tmcallsite *kid;
|
||||
|
||||
site->allocs.bytes.total += site->allocs.bytes.direct;
|
||||
site->allocs.calls.total += site->allocs.calls.direct;
|
||||
for (kid = site->kids; kid; kid = kid->siblings) {
|
||||
compute_callsite_totals(kid);
|
||||
site->allocs.bytes.total += kid->allocs.bytes.total;
|
||||
site->allocs.calls.total += kid->allocs.calls.total;
|
||||
}
|
||||
}
|
||||
|
||||
static void walk_callsite_tree(tmcallsite *site, int level, int kidnum, FILE *fp)
|
||||
{
|
||||
tmcallsite *parent;
|
||||
tmgraphnode *meth, *pmeth, *comp, *pcomp, *lib, *plib;
|
||||
int old_meth_low, old_comp_low, old_lib_low, nkids;
|
||||
tmcallsite *kid;
|
||||
|
||||
parent = site->parent;
|
||||
meth = comp = lib = NULL;
|
||||
if (parent) {
|
||||
meth = site->method;
|
||||
if (meth) {
|
||||
pmeth = parent->method;
|
||||
if (pmeth && pmeth != meth) {
|
||||
if (!meth->low) {
|
||||
meth->allocs.bytes.total += site->allocs.bytes.total;
|
||||
meth->allocs.calls.total += site->allocs.calls.total;
|
||||
}
|
||||
if (!tmgraphnode_connect(pmeth, meth, site))
|
||||
goto bad;
|
||||
|
||||
comp = meth->up;
|
||||
if (comp) {
|
||||
pcomp = pmeth->up;
|
||||
if (pcomp && pcomp != comp) {
|
||||
if (!comp->low) {
|
||||
comp->allocs.bytes.total
|
||||
+= site->allocs.bytes.total;
|
||||
comp->allocs.calls.total
|
||||
+= site->allocs.calls.total;
|
||||
}
|
||||
if (!tmgraphnode_connect(pcomp, comp, site))
|
||||
goto bad;
|
||||
|
||||
lib = comp->up;
|
||||
if (lib) {
|
||||
plib = pcomp->up;
|
||||
if (plib && plib != lib) {
|
||||
if (!lib->low) {
|
||||
lib->allocs.bytes.total
|
||||
+= site->allocs.bytes.total;
|
||||
lib->allocs.calls.total
|
||||
+= site->allocs.calls.total;
|
||||
}
|
||||
if (!tmgraphnode_connect(plib, lib, site))
|
||||
goto bad;
|
||||
}
|
||||
old_lib_low = lib->low;
|
||||
if (!old_lib_low)
|
||||
lib->low = level;
|
||||
}
|
||||
}
|
||||
old_comp_low = comp->low;
|
||||
if (!old_comp_low)
|
||||
comp->low = level;
|
||||
}
|
||||
}
|
||||
old_meth_low = meth->low;
|
||||
if (!old_meth_low)
|
||||
meth->low = level;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_tree_dump) {
|
||||
fprintf(fp, "%c%*s%3d %3d %s %lu %ld\n",
|
||||
site->kids ? '+' : '-', level, "", level, kidnum,
|
||||
meth ? tmgraphnode_name(meth) : "???",
|
||||
(unsigned long)site->allocs.bytes.direct,
|
||||
(long)site->allocs.bytes.total);
|
||||
}
|
||||
nkids = 0;
|
||||
level++;
|
||||
for (kid = site->kids; kid; kid = kid->siblings) {
|
||||
walk_callsite_tree(kid, level, nkids, fp);
|
||||
nkids++;
|
||||
}
|
||||
|
||||
if (meth) {
|
||||
if (!old_meth_low)
|
||||
meth->low = 0;
|
||||
if (comp) {
|
||||
if (!old_comp_low)
|
||||
comp->low = 0;
|
||||
if (lib) {
|
||||
if (!old_lib_low)
|
||||
lib->low = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
bad:
|
||||
perror(program);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linked list bubble-sort (waterson and brendan went bald hacking this).
|
||||
*
|
||||
* Sort the list in non-increasing order, using the expression passed as the
|
||||
* 'lessthan' formal macro parameter. This expression should use 'curr' as
|
||||
* the pointer to the current node (of type nodetype) and 'next' as the next
|
||||
* node pointer. It should return true if curr is less than next, and false
|
||||
* otherwise.
|
||||
*/
|
||||
#define BUBBLE_SORT_LINKED_LIST(listp, nodetype, lessthan) \
|
||||
PR_BEGIN_MACRO \
|
||||
nodetype *curr, **currp, *next, **nextp, *tmp; \
|
||||
\
|
||||
currp = listp; \
|
||||
while ((curr = *currp) != NULL && curr->next) { \
|
||||
nextp = &curr->next; \
|
||||
while ((next = *nextp) != NULL) { \
|
||||
if (lessthan) { \
|
||||
tmp = curr->next; \
|
||||
*currp = tmp; \
|
||||
if (tmp == next) { \
|
||||
PR_ASSERT(nextp == &curr->next); \
|
||||
curr->next = next->next; \
|
||||
next->next = curr; \
|
||||
} else { \
|
||||
*nextp = next->next; \
|
||||
curr->next = next->next; \
|
||||
next->next = tmp; \
|
||||
*currp = next; \
|
||||
*nextp = curr; \
|
||||
nextp = &curr->next; \
|
||||
} \
|
||||
curr = next; \
|
||||
continue; \
|
||||
} \
|
||||
nextp = &next->next; \
|
||||
} \
|
||||
currp = &curr->next; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
static PRIntn tabulate_node(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
tmgraphnode *node = (tmgraphnode*) he;
|
||||
tmgraphnode **table = (tmgraphnode**) arg;
|
||||
|
||||
table[i] = node;
|
||||
BUBBLE_SORT_LINKED_LIST(&node->down, tmgraphnode,
|
||||
(curr->allocs.bytes.total < next->allocs.bytes.total));
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
/* Sort in reverse size order, so biggest node comes first. */
|
||||
static int node_table_compare(const void *p1, const void *p2)
|
||||
{
|
||||
const tmgraphnode *node1, *node2;
|
||||
uint32 key1, key2;
|
||||
|
||||
node1 = *(const tmgraphnode**) p1;
|
||||
node2 = *(const tmgraphnode**) p2;
|
||||
if (sort_by_direct) {
|
||||
key1 = node1->allocs.bytes.direct;
|
||||
key2 = node2->allocs.bytes.direct;
|
||||
} else {
|
||||
key1 = node1->allocs.bytes.total;
|
||||
key2 = node2->allocs.bytes.total;
|
||||
}
|
||||
return (key2 < key1) ? -1 : (key2 > key1) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int mean_size_compare(const void *p1, const void *p2)
|
||||
{
|
||||
const tmgraphnode *node1, *node2;
|
||||
double div1, div2, key1, key2;
|
||||
|
||||
node1 = *(const tmgraphnode**) p1;
|
||||
node2 = *(const tmgraphnode**) p2;
|
||||
div1 = (double)node1->allocs.calls.direct;
|
||||
div2 = (double)node2->allocs.calls.direct;
|
||||
if (div1 == 0 || div2 == 0)
|
||||
return div2 - div1;
|
||||
key1 = (double)node1->allocs.bytes.direct / div1;
|
||||
key2 = (double)node2->allocs.bytes.direct / div2;
|
||||
if (key1 < key2)
|
||||
return 1;
|
||||
if (key1 > key2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *prettybig(uint32 num, char *buf, size_t limit)
|
||||
{
|
||||
if (num >= 1000000000)
|
||||
PR_snprintf(buf, limit, "%1.2fG", (double) num / 1e9);
|
||||
else if (num >= 1000000)
|
||||
PR_snprintf(buf, limit, "%1.2fM", (double) num / 1e6);
|
||||
else if (num >= 1000)
|
||||
PR_snprintf(buf, limit, "%1.2fK", (double) num / 1e3);
|
||||
else
|
||||
PR_snprintf(buf, limit, "%lu", (unsigned long) num);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static double percent(uint32 num, uint32 total)
|
||||
{
|
||||
if (num == 0)
|
||||
return 0.0;
|
||||
return ((double) num * 100) / (double) total;
|
||||
}
|
||||
|
||||
static void sort_graphlink_list(tmgraphlink **listp, int which)
|
||||
{
|
||||
BUBBLE_SORT_LINKED_LIST(listp, tmgraphlink,
|
||||
(TM_LINK_TO_EDGE(curr, which)->allocs.bytes.total
|
||||
< TM_LINK_TO_EDGE(next, which)->allocs.bytes.total));
|
||||
}
|
||||
|
||||
static void dump_graphlink_list(tmgraphlink *list, int which, const char *name,
|
||||
FILE *fp)
|
||||
{
|
||||
tmcounts bytes;
|
||||
tmgraphlink *link;
|
||||
tmgraphedge *edge;
|
||||
char buf[16];
|
||||
|
||||
bytes.direct = bytes.total = 0;
|
||||
for (link = list; link; link = link->next) {
|
||||
edge = TM_LINK_TO_EDGE(link, which);
|
||||
bytes.direct += edge->allocs.bytes.direct;
|
||||
bytes.total += edge->allocs.bytes.total;
|
||||
}
|
||||
|
||||
if (js_mode) {
|
||||
fprintf(fp,
|
||||
" %s:{dbytes:%ld, tbytes:%ld, edges:[\n",
|
||||
name, (long) bytes.direct, (long) bytes.total);
|
||||
for (link = list; link; link = link->next) {
|
||||
edge = TM_LINK_TO_EDGE(link, which);
|
||||
fprintf(fp,
|
||||
" {node:%d, dbytes:%ld, tbytes:%ld},\n",
|
||||
link->node->sort,
|
||||
(long) edge->allocs.bytes.direct,
|
||||
(long) edge->allocs.bytes.total);
|
||||
}
|
||||
fputs(" ]},\n", fp);
|
||||
} else {
|
||||
fputs("<td valign=top>", fp);
|
||||
for (link = list; link; link = link->next) {
|
||||
edge = TM_LINK_TO_EDGE(link, which);
|
||||
fprintf(fp,
|
||||
"<a href='#%s'>%s (%1.2f%%)</a>\n",
|
||||
tmgraphnode_name(link->node),
|
||||
prettybig(edge->allocs.bytes.total, buf, sizeof buf),
|
||||
percent(edge->allocs.bytes.total, bytes.total));
|
||||
}
|
||||
fputs("</td>", fp);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_graph(tmreader *tmr, PLHashTable *hashtbl, const char *varname,
|
||||
const char *title, FILE *fp)
|
||||
{
|
||||
uint32 i, count;
|
||||
tmgraphnode **table, *node;
|
||||
char *name;
|
||||
size_t namelen;
|
||||
char buf1[16], buf2[16], buf3[16], buf4[16];
|
||||
static char NA[] = "N/A";
|
||||
|
||||
count = hashtbl->nentries;
|
||||
table = (tmgraphnode**) malloc(count * sizeof(tmgraphnode*));
|
||||
if (!table) {
|
||||
perror(program);
|
||||
exit(1);
|
||||
}
|
||||
PL_HashTableEnumerateEntries(hashtbl, tabulate_node, table);
|
||||
qsort(table, count, sizeof(tmgraphnode*), node_table_compare);
|
||||
for (i = 0; i < count; i++)
|
||||
table[i]->sort = i;
|
||||
|
||||
if (js_mode) {
|
||||
fprintf(fp,
|
||||
"var %s = {\n name:'%s', title:'%s', nodes:[\n",
|
||||
varname, varname, title);
|
||||
} else {
|
||||
fprintf(fp,
|
||||
"<table border=1>\n"
|
||||
"<tr>"
|
||||
"<th>%s</th>"
|
||||
"<th>Down</th>"
|
||||
"<th>Next</th>"
|
||||
"<th>Total/Direct (percents)</th>"
|
||||
"<th>Allocations</th>"
|
||||
"<th>Fan-in</th>"
|
||||
"<th>Fan-out</th>"
|
||||
"</tr>\n",
|
||||
title);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Don't bother with truly puny nodes. */
|
||||
node = table[i];
|
||||
if (node->allocs.bytes.total < min_subtotal)
|
||||
break;
|
||||
|
||||
name = tmgraphnode_name(node);
|
||||
if (js_mode) {
|
||||
fprintf(fp,
|
||||
" {name:'%s', dbytes:%ld, tbytes:%ld,"
|
||||
" dallocs:%ld, tallocs:%ld,\n",
|
||||
name,
|
||||
(long) node->allocs.bytes.direct,
|
||||
(long) node->allocs.bytes.total,
|
||||
(long) node->allocs.calls.direct,
|
||||
(long) node->allocs.calls.total);
|
||||
} else {
|
||||
namelen = strlen(name);
|
||||
fprintf(fp,
|
||||
"<tr>"
|
||||
"<td valign=top><a name='%s'>%.*s%s</a></td>",
|
||||
name,
|
||||
(namelen > 40) ? 40 : (int)namelen, name,
|
||||
(namelen > 40) ? "<i>...</i>" : "");
|
||||
if (node->down) {
|
||||
fprintf(fp,
|
||||
"<td valign=top><a href='#%s'><i>down</i></a></td>",
|
||||
tmgraphnode_name(node->down));
|
||||
} else {
|
||||
fputs("<td></td>", fp);
|
||||
}
|
||||
if (node->next) {
|
||||
fprintf(fp,
|
||||
"<td valign=top><a href='#%s'><i>next</i></a></td>",
|
||||
tmgraphnode_name(node->next));
|
||||
} else {
|
||||
fputs("<td></td>", fp);
|
||||
}
|
||||
fprintf(fp,
|
||||
"<td valign=top>%s/%s (%1.2f%%/%1.2f%%)</td>"
|
||||
"<td valign=top>%s/%s (%1.2f%%/%1.2f%%)</td>",
|
||||
prettybig(node->allocs.bytes.total, buf1, sizeof buf1),
|
||||
prettybig(node->allocs.bytes.direct, buf2, sizeof buf2),
|
||||
percent(node->allocs.bytes.total,
|
||||
tmr->calltree_root.allocs.bytes.total),
|
||||
percent(node->allocs.bytes.direct,
|
||||
tmr->calltree_root.allocs.bytes.total),
|
||||
prettybig(node->allocs.calls.total, buf3, sizeof buf3),
|
||||
prettybig(node->allocs.calls.direct, buf4, sizeof buf4),
|
||||
percent(node->allocs.calls.total,
|
||||
tmr->calltree_root.allocs.calls.total),
|
||||
percent(node->allocs.calls.direct,
|
||||
tmr->calltree_root.allocs.calls.total));
|
||||
}
|
||||
|
||||
/* NB: we must use 'fin' because 'in' is a JS keyword! */
|
||||
sort_graphlink_list(&node->in, TM_EDGE_IN_LINK);
|
||||
dump_graphlink_list(node->in, TM_EDGE_IN_LINK, "fin", fp);
|
||||
sort_graphlink_list(&node->out, TM_EDGE_OUT_LINK);
|
||||
dump_graphlink_list(node->out, TM_EDGE_OUT_LINK, "out", fp);
|
||||
|
||||
if (js_mode)
|
||||
fputs(" },\n", fp);
|
||||
else
|
||||
fputs("</tr>\n", fp);
|
||||
}
|
||||
|
||||
if (js_mode) {
|
||||
fputs("]};\n", fp);
|
||||
} else {
|
||||
fputs("</table>\n<hr>\n", fp);
|
||||
|
||||
qsort(table, count, sizeof(tmgraphnode*), mean_size_compare);
|
||||
|
||||
fprintf(fp,
|
||||
"<table border=1>\n"
|
||||
"<tr><th colspan=4>Direct Allocators</th></tr>\n"
|
||||
"<tr>"
|
||||
"<th>%s</th>"
|
||||
"<th>Mean Size</th>"
|
||||
"<th>StdDev</th>"
|
||||
"<th>Allocations<th>"
|
||||
"</tr>\n",
|
||||
title);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
double allocs, bytes, mean, variance, sigma;
|
||||
|
||||
node = table[i];
|
||||
allocs = (double)node->allocs.calls.direct;
|
||||
if (!allocs)
|
||||
continue;
|
||||
|
||||
/* Compute direct-size mean and standard deviation. */
|
||||
bytes = (double)node->allocs.bytes.direct;
|
||||
mean = bytes / allocs;
|
||||
variance = allocs * node->sqsum - bytes * bytes;
|
||||
if (variance < 0 || allocs == 1)
|
||||
variance = 0;
|
||||
else
|
||||
variance /= allocs * (allocs - 1);
|
||||
sigma = sqrt(variance);
|
||||
|
||||
name = tmgraphnode_name(node);
|
||||
namelen = strlen(name);
|
||||
fprintf(fp,
|
||||
"<tr>"
|
||||
"<td valign=top>%.*s%s</td>"
|
||||
"<td valign=top>%s</td>"
|
||||
"<td valign=top>%s</td>"
|
||||
"<td valign=top>%s</td>"
|
||||
"</tr>\n",
|
||||
(namelen > 65) ? 45 : (int)namelen, name,
|
||||
(namelen > 65) ? "<i>...</i>" : "",
|
||||
prettybig((uint32)mean, buf1, sizeof buf1),
|
||||
prettybig((uint32)sigma, buf2, sizeof buf2),
|
||||
prettybig(node->allocs.calls.direct, buf3, sizeof buf3));
|
||||
}
|
||||
fputs("</table>\n", fp);
|
||||
}
|
||||
|
||||
free((void*) table);
|
||||
}
|
||||
|
||||
static void my_tmevent_handler(tmreader *tmr, tmevent *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case TM_EVENT_STATS:
|
||||
if (js_mode)
|
||||
break;
|
||||
fprintf(stdout,
|
||||
"<p><table border=1>"
|
||||
"<tr><th>Counter</th><th>Value</th></tr>\n"
|
||||
"<tr><td>maximum actual stack depth</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>maximum callsite tree depth</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>number of parent callsites</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>maximum kids per parent</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>hits looking for a kid</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>misses looking for a kid</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>steps over other kids</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>callsite recurrences</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>number of stack backtraces</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>backtrace failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>backtrace malloc failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>backtrace dladdr failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>malloc calls</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>malloc failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>calloc calls</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>calloc failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>realloc calls</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>realloc failures</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>free calls</td><td align=right>%lu</td></tr>\n"
|
||||
"<tr><td>free(null) calls</td><td align=right>%lu</td></tr>\n"
|
||||
"</table>",
|
||||
(unsigned long) event->u.stats.tmstats.calltree_maxstack,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_maxdepth,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_parents,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_maxkids,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_kidhits,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_kidmisses,
|
||||
(unsigned long) event->u.stats.tmstats.calltree_kidsteps,
|
||||
(unsigned long) event->u.stats.tmstats.callsite_recurrences,
|
||||
(unsigned long) event->u.stats.tmstats.backtrace_calls,
|
||||
(unsigned long) event->u.stats.tmstats.backtrace_failures,
|
||||
(unsigned long) event->u.stats.tmstats.btmalloc_failures,
|
||||
(unsigned long) event->u.stats.tmstats.dladdr_failures,
|
||||
(unsigned long) event->u.stats.tmstats.malloc_calls,
|
||||
(unsigned long) event->u.stats.tmstats.malloc_failures,
|
||||
(unsigned long) event->u.stats.tmstats.calloc_calls,
|
||||
(unsigned long) event->u.stats.tmstats.calloc_failures,
|
||||
(unsigned long) event->u.stats.tmstats.realloc_calls,
|
||||
(unsigned long) event->u.stats.tmstats.realloc_failures,
|
||||
(unsigned long) event->u.stats.tmstats.free_calls,
|
||||
(unsigned long) event->u.stats.tmstats.null_free_calls);
|
||||
|
||||
if (event->u.stats.calltree_maxkids_parent) {
|
||||
tmcallsite *site =
|
||||
tmreader_callsite(tmr, event->u.stats.calltree_maxkids_parent);
|
||||
if (site && site->method) {
|
||||
fprintf(stdout, "<p>callsite with the most kids: %s</p>",
|
||||
tmgraphnode_name(site->method));
|
||||
}
|
||||
}
|
||||
|
||||
if (event->u.stats.calltree_maxstack_top) {
|
||||
tmcallsite *site =
|
||||
tmreader_callsite(tmr, event->u.stats.calltree_maxstack_top);
|
||||
fputs("<p>deepest callsite tree path:\n"
|
||||
"<table border=1>\n"
|
||||
"<tr><th>Method</th><th>Offset</th></tr>\n",
|
||||
stdout);
|
||||
while (site) {
|
||||
fprintf(stdout,
|
||||
"<tr><td>%s</td><td>0x%08lX</td></tr>\n",
|
||||
site->method ? tmgraphnode_name(site->method) : "???",
|
||||
(unsigned long) site->offset);
|
||||
site = site->parent;
|
||||
}
|
||||
fputs("</table>\n<hr>\n", stdout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c, i, j, rv;
|
||||
tmreader *tmr;
|
||||
FILE *fp;
|
||||
|
||||
program = *argv;
|
||||
tmr = tmreader_new(program, NULL);
|
||||
if (!tmr) {
|
||||
perror(program);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv, "djtuf:m:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
sort_by_direct = 1;
|
||||
break;
|
||||
case 'j':
|
||||
js_mode = 1;
|
||||
break;
|
||||
case 't':
|
||||
do_tree_dump = 1;
|
||||
break;
|
||||
case 'u':
|
||||
unified_output = 1;
|
||||
break;
|
||||
case 'f':
|
||||
function_dump = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
min_subtotal = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"usage: %s [-dtu] [-f function-dump-filename] [-m min] [output.html]\n",
|
||||
program);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!js_mode) {
|
||||
time_t start = time(NULL);
|
||||
|
||||
fprintf(stdout,
|
||||
"<script language=\"JavaScript\">\n"
|
||||
"function onload() {\n"
|
||||
" document.links[0].__proto__.onmouseover = new Function("
|
||||
"\"window.status ="
|
||||
" this.href.substring(this.href.lastIndexOf('#') + 1)\");\n"
|
||||
"}\n"
|
||||
"</script>\n");
|
||||
fprintf(stdout, "%s starting at %s", program, ctime(&start));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc == 0) {
|
||||
if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0)
|
||||
exit(1);
|
||||
} else {
|
||||
for (i = j = 0; i < argc; i++) {
|
||||
fp = fopen(argv[i], "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: can't open %s: %s\n",
|
||||
program, argv[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler);
|
||||
if (rv < 0)
|
||||
exit(1);
|
||||
if (rv > 0)
|
||||
j++;
|
||||
fclose(fp);
|
||||
}
|
||||
if (j == 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
compute_callsite_totals(&tmr->calltree_root);
|
||||
walk_callsite_tree(&tmr->calltree_root, 0, 0, stdout);
|
||||
|
||||
if (js_mode) {
|
||||
fprintf(stdout,
|
||||
"<script language='javascript'>\n"
|
||||
"// direct and total byte and allocator-call counts\n"
|
||||
"var dbytes = %ld, tbytes = %ld,"
|
||||
" dallocs = %ld, tallocs = %ld;\n",
|
||||
(long) tmr->calltree_root.allocs.bytes.direct,
|
||||
(long) tmr->calltree_root.allocs.bytes.total,
|
||||
(long) tmr->calltree_root.allocs.calls.direct,
|
||||
(long) tmr->calltree_root.allocs.calls.total);
|
||||
}
|
||||
|
||||
dump_graph(tmr, tmr->libraries, "libraries", "Library", stdout);
|
||||
if (!js_mode)
|
||||
fputs("<hr>\n", stdout);
|
||||
|
||||
dump_graph(tmr, tmr->components, "classes", "Class or Component", stdout);
|
||||
if (js_mode || unified_output || function_dump) {
|
||||
if (js_mode || unified_output || strcmp(function_dump, "-") == 0) {
|
||||
fp = stdout;
|
||||
if (!js_mode)
|
||||
fputs("<hr>\n", fp);
|
||||
} else {
|
||||
struct stat sb, fsb;
|
||||
|
||||
fstat(fileno(stdout), &sb);
|
||||
if (stat(function_dump, &fsb) == 0 &&
|
||||
fsb.st_dev == sb.st_dev && fsb.st_ino == sb.st_ino) {
|
||||
fp = stdout;
|
||||
fputs("<hr>\n", fp);
|
||||
} else {
|
||||
fp = fopen(function_dump, "w");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: can't open %s: %s\n",
|
||||
program, function_dump, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dump_graph(tmr, tmr->methods, "methods", "Function or Method", fp);
|
||||
if (fp != stdout)
|
||||
fclose(fp);
|
||||
|
||||
if (js_mode) {
|
||||
fputs("function viewnode(graph, index) {\n"
|
||||
" view.location = viewsrc();\n"
|
||||
"}\n"
|
||||
"function viewnodelink(graph, index) {\n"
|
||||
" var node = graph.nodes[index];\n"
|
||||
" return '<a href=\"javascript:viewnode('"
|
||||
" + graph.name.quote() + ', ' + node.sort"
|
||||
" + ')\" onmouseover=' + node.name.quote() + '>'"
|
||||
" + node.name + '</a>';\n"
|
||||
"}\n"
|
||||
"function search(expr) {\n"
|
||||
" var re = new RegExp(expr);\n"
|
||||
" var src = '';\n"
|
||||
" var graphs = [libraries, classes, methods]\n"
|
||||
" var nodes;\n"
|
||||
" for (var n = 0; n < (nodes = graphs[n].nodes).length; n++) {\n"
|
||||
" for (var i = 0; i < nodes.length; i++) {\n"
|
||||
" if (re.test(nodes[i].name))\n"
|
||||
" src += viewnodelink(graph, i) + '\\n';\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" view.location = viewsrc();\n"
|
||||
"}\n"
|
||||
"function ctrlsrc() {\n"
|
||||
" return \"<form>\\n"
|
||||
"search: <input size=40 onchange='search(this.value)'>\\n"
|
||||
"</form>\\n\";\n"
|
||||
"}\n"
|
||||
"function viewsrc() {\n"
|
||||
" return 'hiiiii'\n"
|
||||
"}\n"
|
||||
"</script>\n"
|
||||
"<frameset rows='10%,*'>\n"
|
||||
" <frame name='ctrl' src='javascript:top.ctrlsrc()'>\n"
|
||||
" <frame name='view' src='javascript:top.viewsrc()'>\n"
|
||||
"</frameset>\n",
|
||||
stdout);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
1301
mozilla/tools/trace-malloc/lib/nsTraceMalloc.c
Normal file
1301
mozilla/tools/trace-malloc/lib/nsTraceMalloc.c
Normal file
File diff suppressed because it is too large
Load Diff
173
mozilla/tools/trace-malloc/lib/nsTraceMalloc.h
Normal file
173
mozilla/tools/trace-malloc/lib/nsTraceMalloc.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is nsTraceMalloc.c/bloatblame.c code, released
|
||||
* April 19, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich, 14-April-2000
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the MPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the MPL or the GPL.
|
||||
*/
|
||||
#ifndef nsTraceMalloc_h___
|
||||
#define nsTraceMalloc_h___
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/**
|
||||
* Magic "number" at start of a trace-malloc log file. Inspired by the PNG
|
||||
* magic string, which inspired XPCOM's typelib (.xpt) file magic. See the
|
||||
* NS_TraceMallocStartup comment (below) for magic number differences in log
|
||||
* file structure.
|
||||
*/
|
||||
#define NS_TRACE_MALLOC_MAGIC "XPCOM\nTMLog03\r\n\032"
|
||||
#define NS_TRACE_MALLOC_MAGIC_SIZE 16
|
||||
|
||||
/**
|
||||
* Trace-malloc stats, traced via the 'Z' event at the end of a log file.
|
||||
*/
|
||||
typedef struct nsTMStats {
|
||||
uint32 calltree_maxstack;
|
||||
uint32 calltree_maxdepth;
|
||||
uint32 calltree_parents;
|
||||
uint32 calltree_maxkids;
|
||||
uint32 calltree_kidhits;
|
||||
uint32 calltree_kidmisses;
|
||||
uint32 calltree_kidsteps;
|
||||
uint32 callsite_recurrences;
|
||||
uint32 backtrace_calls;
|
||||
uint32 backtrace_failures;
|
||||
uint32 btmalloc_failures;
|
||||
uint32 dladdr_failures;
|
||||
uint32 malloc_calls;
|
||||
uint32 malloc_failures;
|
||||
uint32 calloc_calls;
|
||||
uint32 calloc_failures;
|
||||
uint32 realloc_calls;
|
||||
uint32 realloc_failures;
|
||||
uint32 free_calls;
|
||||
uint32 null_free_calls;
|
||||
} nsTMStats;
|
||||
|
||||
#define NS_TMSTATS_STATIC_INITIALIZER {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
||||
|
||||
/**
|
||||
* Call NS_TraceMallocStartup with a valid file descriptor to enable logging
|
||||
* of compressed malloc traces, including callsite chains. Integers may be
|
||||
* unsigned serial numbers, sizes, or offsets, and require at most 32 bits.
|
||||
* They're encoded as follows:
|
||||
* 0-127 0xxxxxxx (binary, one byte)
|
||||
* 128-16383 10xxxxxx xxxxxxxx
|
||||
* 16384-0x1fffff 110xxxxx xxxxxxxx xxxxxxxx
|
||||
* 0x200000-0xfffffff 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx
|
||||
* 0x10000000-0xffffffff 11110000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
|
||||
* Strings are NUL-terminated ASCII.
|
||||
*
|
||||
* Event Operands (magic TMLog01)
|
||||
* 'L' library serial, shared object filename string
|
||||
* 'N' method serial, library serial, demangled name string
|
||||
* 'S' site serial, parent serial, method serial, calling pc offset
|
||||
* 'M' site serial, malloc size
|
||||
* 'C' site serial, calloc size
|
||||
* 'R' site serial, realloc oldsize, realloc size
|
||||
* 'F' site serial, free size
|
||||
*
|
||||
* Event Operands (magic TMLog02)
|
||||
* 'Z' serialized struct tmstats (20 unsigned integers),
|
||||
* maxkids parent callsite serial,
|
||||
* maxstack top callsite serial
|
||||
*
|
||||
* Event Operands (magic TMLog03)
|
||||
* 'T' seconds, microseconds, caption
|
||||
*
|
||||
* See xpcom/base/bloatblame.c for an example log-file reader.
|
||||
*/
|
||||
#define TM_EVENT_LIBRARY 'L'
|
||||
#define TM_EVENT_METHOD 'N'
|
||||
#define TM_EVENT_CALLSITE 'S'
|
||||
#define TM_EVENT_MALLOC 'M'
|
||||
#define TM_EVENT_CALLOC 'C'
|
||||
#define TM_EVENT_REALLOC 'R'
|
||||
#define TM_EVENT_FREE 'F'
|
||||
#define TM_EVENT_STATS 'Z'
|
||||
#define TM_EVENT_TIMESTAMP 'T'
|
||||
|
||||
PR_EXTERN(void) NS_TraceMallocStartup(int logfd);
|
||||
|
||||
/**
|
||||
* Initialize malloc tracing, using the ``standard'' startup arguments.
|
||||
*/
|
||||
PR_EXTERN(int) NS_TraceMallocStartupArgs(int argc, char* argv[]);
|
||||
|
||||
/**
|
||||
* Stop all malloc tracing, flushing any buffered events to the logfile.
|
||||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocShutdown(void);
|
||||
|
||||
/**
|
||||
* Disable malloc tracing.
|
||||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocDisable(void);
|
||||
|
||||
/**
|
||||
* Enable malloc tracing.
|
||||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocEnable(void);
|
||||
|
||||
/**
|
||||
* Change the log file descriptor, flushing any buffered output to the old
|
||||
* fd, and writing NS_TRACE_MALLOC_MAGIC to the new file if it is zero length.
|
||||
* Return the old fd, so the caller can swap open fds. Return -2 on failure,
|
||||
* which means malloc failure.
|
||||
*/
|
||||
PR_EXTERN(int) NS_TraceMallocChangeLogFD(int fd);
|
||||
|
||||
/**
|
||||
* Close the file descriptor fd and forget any bookkeeping associated with it.
|
||||
* Do nothing if fd is -1.
|
||||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd);
|
||||
|
||||
/**
|
||||
* Emit a timestamp event with the given caption to the current log file.
|
||||
*/
|
||||
PR_EXTERN(void) NS_TraceMallocLogTimestamp(const char *caption);
|
||||
|
||||
/**
|
||||
* Dump a human-readable listing of current allocations and their compressed
|
||||
* stack backtraces to the file named by pathname. Beware this file may have
|
||||
* very long lines.
|
||||
*
|
||||
* Return -1 on error with errno set by the system, 0 on success.
|
||||
*/
|
||||
PR_EXTERN(int)
|
||||
NS_TraceMallocDumpAllocations(const char *pathname);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* nsTraceMalloc_h___ */
|
||||
700
mozilla/tools/trace-malloc/tmreader.c
Normal file
700
mozilla/tools/trace-malloc/tmreader.c
Normal file
@@ -0,0 +1,700 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is tmreader.h/tmreader.c code, released
|
||||
* July 7, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich, 7-July-2000
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the MPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the MPL or the GPL.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h> /* XXX push error reporting out to clients? */
|
||||
#include <unistd.h>
|
||||
#include "prlog.h"
|
||||
#include "plhash.h"
|
||||
#include "nsTraceMalloc.h"
|
||||
#include "tmreader.h"
|
||||
|
||||
static int accum_byte(FILE *fp, uint32 *uip)
|
||||
{
|
||||
int c = getc(fp);
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
*uip = (*uip << 8) | c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_uint32(FILE *fp, uint32 *uip)
|
||||
{
|
||||
int c;
|
||||
uint32 ui;
|
||||
|
||||
c = getc(fp);
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
ui = 0;
|
||||
if (c & 0x80) {
|
||||
c &= 0x7f;
|
||||
if (c & 0x40) {
|
||||
c &= 0x3f;
|
||||
if (c & 0x20) {
|
||||
c &= 0x1f;
|
||||
if (c & 0x10) {
|
||||
if (!accum_byte(fp, &ui))
|
||||
return 0;
|
||||
} else {
|
||||
ui = (uint32) c;
|
||||
}
|
||||
if (!accum_byte(fp, &ui))
|
||||
return 0;
|
||||
} else {
|
||||
ui = (uint32) c;
|
||||
}
|
||||
if (!accum_byte(fp, &ui))
|
||||
return 0;
|
||||
} else {
|
||||
ui = (uint32) c;
|
||||
}
|
||||
if (!accum_byte(fp, &ui))
|
||||
return 0;
|
||||
} else {
|
||||
ui = (uint32) c;
|
||||
}
|
||||
*uip = ui;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *get_string(FILE *fp)
|
||||
{
|
||||
char *cp;
|
||||
int c;
|
||||
static char buf[256];
|
||||
static char *bp = buf, *ep = buf + sizeof buf;
|
||||
static size_t bsize = sizeof buf;
|
||||
|
||||
cp = bp;
|
||||
do {
|
||||
c = getc(fp);
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
if (cp == ep) {
|
||||
if (bp == buf) {
|
||||
bp = malloc(2 * bsize);
|
||||
if (bp)
|
||||
memcpy(bp, buf, bsize);
|
||||
} else {
|
||||
bp = realloc(bp, 2 * bsize);
|
||||
}
|
||||
if (!bp)
|
||||
return 0;
|
||||
cp = bp + bsize;
|
||||
bsize *= 2;
|
||||
ep = bp + bsize;
|
||||
}
|
||||
*cp++ = c;
|
||||
} while (c != '\0');
|
||||
return strdup(bp);
|
||||
}
|
||||
|
||||
static int get_tmevent(FILE *fp, tmevent *event)
|
||||
{
|
||||
int c;
|
||||
char *s;
|
||||
|
||||
c = getc(fp);
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
event->type = (char) c;
|
||||
if (!get_uint32(fp, &event->serial))
|
||||
return 0;
|
||||
switch (c) {
|
||||
case TM_EVENT_LIBRARY:
|
||||
s = get_string(fp);
|
||||
if (!s)
|
||||
return 0;
|
||||
event->u.libname = s;
|
||||
break;
|
||||
|
||||
case TM_EVENT_METHOD:
|
||||
if (!get_uint32(fp, &event->u.method.library))
|
||||
return 0;
|
||||
s = get_string(fp);
|
||||
if (!s)
|
||||
return 0;
|
||||
event->u.method.name = s;
|
||||
break;
|
||||
|
||||
case TM_EVENT_CALLSITE:
|
||||
if (!get_uint32(fp, &event->u.site.parent))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.site.method))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.site.offset))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TM_EVENT_MALLOC:
|
||||
case TM_EVENT_CALLOC:
|
||||
case TM_EVENT_FREE:
|
||||
event->u.alloc.oldsize = 0;
|
||||
if (!get_uint32(fp, &event->u.alloc.size))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TM_EVENT_REALLOC:
|
||||
if (!get_uint32(fp, &event->u.alloc.oldsize))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.alloc.size))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TM_EVENT_STATS:
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxstack))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxdepth))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_parents))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxkids))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidhits))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidmisses))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidsteps))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.callsite_recurrences))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.btmalloc_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.dladdr_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.malloc_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.malloc_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calloc_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.calloc_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.realloc_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.realloc_failures))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.free_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.tmstats.null_free_calls))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.calltree_maxkids_parent))
|
||||
return 0;
|
||||
if (!get_uint32(fp, &event->u.stats.calltree_maxstack_top))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *generic_alloctable(void *pool, PRSize size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void generic_freetable(void *pool, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
static PLHashEntry *callsite_allocentry(void *pool, const void *key)
|
||||
{
|
||||
return malloc(sizeof(tmcallsite));
|
||||
}
|
||||
|
||||
static PLHashEntry *graphnode_allocentry(void *pool, const void *key)
|
||||
{
|
||||
tmgraphnode *node = (tmgraphnode*) malloc(sizeof(tmgraphnode));
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->in = node->out = NULL;
|
||||
node->up = node->down = node->next = NULL;
|
||||
node->low = 0;
|
||||
node->allocs.bytes.direct = node->allocs.bytes.total = 0;
|
||||
node->allocs.calls.direct = node->allocs.calls.total = 0;
|
||||
node->frees.bytes.direct = node->frees.bytes.total = 0;
|
||||
node->frees.calls.direct = node->frees.calls.total = 0;
|
||||
node->sqsum = 0;
|
||||
node->sort = -1;
|
||||
return &node->entry;
|
||||
}
|
||||
|
||||
static void graphnode_freeentry(void *pool, PLHashEntry *he, PRUintn flag)
|
||||
{
|
||||
/* Always free the value, which points to a strdup'd string. */
|
||||
free(he->value);
|
||||
|
||||
/* Free the whole thing if we're told to. */
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
free((void*) he);
|
||||
}
|
||||
|
||||
static void component_freeentry(void *pool, PLHashEntry *he, PRUintn flag)
|
||||
{
|
||||
if (flag == HT_FREE_ENTRY) {
|
||||
tmgraphnode *comp = (tmgraphnode*) he;
|
||||
|
||||
/* Free the key, which was strdup'd (N.B. value also points to it). */
|
||||
free((void*) tmcomponent_name(comp));
|
||||
free((void*) comp);
|
||||
}
|
||||
}
|
||||
|
||||
static PLHashAllocOps callsite_hashallocops = {
|
||||
generic_alloctable, generic_freetable,
|
||||
callsite_allocentry, graphnode_freeentry
|
||||
};
|
||||
|
||||
static PLHashAllocOps graphnode_hashallocops = {
|
||||
generic_alloctable, generic_freetable,
|
||||
graphnode_allocentry, graphnode_freeentry
|
||||
};
|
||||
|
||||
static PLHashAllocOps component_hashallocops = {
|
||||
generic_alloctable, generic_freetable,
|
||||
graphnode_allocentry, component_freeentry
|
||||
};
|
||||
|
||||
static PLHashNumber hash_serial(const void *key)
|
||||
{
|
||||
return (PLHashNumber) key;
|
||||
}
|
||||
|
||||
tmreader *tmreader_new(const char *program, void *data)
|
||||
{
|
||||
tmreader *tmr;
|
||||
|
||||
tmr = calloc(1, sizeof *tmr);
|
||||
if (!tmr)
|
||||
return NULL;
|
||||
tmr->program = program;
|
||||
tmr->data = data;
|
||||
|
||||
tmr->libraries = PL_NewHashTable(100, hash_serial, PL_CompareValues,
|
||||
PL_CompareStrings, &graphnode_hashallocops,
|
||||
NULL);
|
||||
tmr->components = PL_NewHashTable(10000, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, &component_hashallocops,
|
||||
NULL);
|
||||
tmr->methods = PL_NewHashTable(10000, hash_serial, PL_CompareValues,
|
||||
PL_CompareStrings, &graphnode_hashallocops,
|
||||
NULL);
|
||||
tmr->callsites = PL_NewHashTable(200000, hash_serial, PL_CompareValues,
|
||||
PL_CompareValues, &callsite_hashallocops,
|
||||
NULL);
|
||||
tmr->calltree_root.entry.value = (void*) strdup("root");
|
||||
|
||||
if (!tmr->libraries || !tmr->components || !tmr->methods ||
|
||||
!tmr->callsites || !tmr->calltree_root.entry.value) {
|
||||
tmreader_destroy(tmr);
|
||||
return NULL;
|
||||
}
|
||||
return tmr;
|
||||
}
|
||||
|
||||
void tmreader_destroy(tmreader *tmr)
|
||||
{
|
||||
if (tmr->libraries)
|
||||
PL_HashTableDestroy(tmr->libraries);
|
||||
if (tmr->components)
|
||||
PL_HashTableDestroy(tmr->components);
|
||||
if (tmr->methods)
|
||||
PL_HashTableDestroy(tmr->methods);
|
||||
if (tmr->callsites)
|
||||
PL_HashTableDestroy(tmr->callsites);
|
||||
free(tmr);
|
||||
}
|
||||
|
||||
int tmreader_eventloop(tmreader *tmr, const char *filename,
|
||||
tmeventhandler eventhandler)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[NS_TRACE_MALLOC_MAGIC_SIZE];
|
||||
tmevent event;
|
||||
static const char magic[] = NS_TRACE_MALLOC_MAGIC;
|
||||
|
||||
if (strcmp(filename, "-") == 0) {
|
||||
fp = stdin;
|
||||
} else {
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: can't open %s: %s.\n",
|
||||
tmr->program, filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (read(fileno(fp), buf, sizeof buf) != sizeof buf ||
|
||||
strncmp(buf, magic, sizeof buf) != 0) {
|
||||
fprintf(stderr, "%s: bad magic string %s at start of %s.\n",
|
||||
tmr->program, buf, filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (get_tmevent(fp, &event)) {
|
||||
switch (event.type) {
|
||||
case TM_EVENT_LIBRARY: {
|
||||
const void *key;
|
||||
PLHashNumber hash;
|
||||
PLHashEntry **hep, *he;
|
||||
|
||||
key = (const void*) event.serial;
|
||||
hash = hash_serial(key);
|
||||
hep = PL_HashTableRawLookup(tmr->libraries, hash, key);
|
||||
he = *hep;
|
||||
PR_ASSERT(!he);
|
||||
if (he) exit(2);
|
||||
|
||||
he = PL_HashTableRawAdd(tmr->libraries, hep, hash, key,
|
||||
event.u.libname);
|
||||
if (!he) {
|
||||
perror(tmr->program);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TM_EVENT_METHOD: {
|
||||
const void *key;
|
||||
PLHashNumber hash;
|
||||
PLHashEntry **hep, *he;
|
||||
char *name, *head, *mark, save;
|
||||
tmgraphnode *meth, *comp, *lib;
|
||||
|
||||
key = (const void*) event.serial;
|
||||
hash = hash_serial(key);
|
||||
hep = PL_HashTableRawLookup(tmr->methods, hash, key);
|
||||
he = *hep;
|
||||
PR_ASSERT(!he);
|
||||
if (he) exit(2);
|
||||
|
||||
name = event.u.method.name;
|
||||
he = PL_HashTableRawAdd(tmr->methods, hep, hash, key, name);
|
||||
if (!he) {
|
||||
perror(tmr->program);
|
||||
return -1;
|
||||
}
|
||||
meth = (tmgraphnode*) he;
|
||||
|
||||
head = name;
|
||||
mark = strchr(name, ':');
|
||||
if (!mark) {
|
||||
mark = name;
|
||||
while (*mark != '\0' && *mark == '_')
|
||||
mark++;
|
||||
head = mark;
|
||||
mark = strchr(head, '_');
|
||||
if (!mark) {
|
||||
mark = strchr(head, '+');
|
||||
if (!mark)
|
||||
mark = head + strlen(head);
|
||||
}
|
||||
}
|
||||
|
||||
save = *mark;
|
||||
*mark = '\0';
|
||||
hash = PL_HashString(head);
|
||||
hep = PL_HashTableRawLookup(tmr->components, hash, head);
|
||||
he = *hep;
|
||||
if (he) {
|
||||
comp = (tmgraphnode*) he;
|
||||
} else {
|
||||
head = strdup(head);
|
||||
if (head) {
|
||||
he = PL_HashTableRawAdd(tmr->components, hep, hash, head,
|
||||
head);
|
||||
}
|
||||
if (!he) {
|
||||
perror(tmr->program);
|
||||
return -1;
|
||||
}
|
||||
comp = (tmgraphnode*) he;
|
||||
|
||||
key = (const void*) event.u.method.library;
|
||||
hash = hash_serial(key);
|
||||
lib = (tmgraphnode*)
|
||||
*PL_HashTableRawLookup(tmr->libraries, hash, key);
|
||||
if (lib) {
|
||||
comp->up = lib;
|
||||
comp->next = lib->down;
|
||||
lib->down = comp;
|
||||
}
|
||||
}
|
||||
*mark = save;
|
||||
|
||||
meth->up = comp;
|
||||
meth->next = comp->down;
|
||||
comp->down = meth;
|
||||
break;
|
||||
}
|
||||
|
||||
case TM_EVENT_CALLSITE: {
|
||||
const void *key, *mkey;
|
||||
PLHashNumber hash, mhash;
|
||||
PLHashEntry **hep, *he;
|
||||
tmcallsite *site, *parent;
|
||||
tmgraphnode *meth;
|
||||
|
||||
key = (const void*) event.serial;
|
||||
hash = hash_serial(key);
|
||||
hep = PL_HashTableRawLookup(tmr->callsites, hash, key);
|
||||
he = *hep;
|
||||
PR_ASSERT(!he);
|
||||
if (he) exit(2);
|
||||
|
||||
if (event.u.site.parent == 0) {
|
||||
parent = &tmr->calltree_root;
|
||||
} else {
|
||||
parent = tmreader_callsite(tmr, event.u.site.parent);
|
||||
if (!parent) {
|
||||
fprintf(stderr, "%s: no parent for %lu (%lu)!\n",
|
||||
tmr->program, (unsigned long) event.serial,
|
||||
(unsigned long) event.u.site.parent);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
he = PL_HashTableRawAdd(tmr->callsites, hep, hash, key, NULL);
|
||||
if (!he) {
|
||||
perror(tmr->program);
|
||||
return -1;
|
||||
}
|
||||
|
||||
site = (tmcallsite*) he;
|
||||
site->parent = parent;
|
||||
site->siblings = parent->kids;
|
||||
parent->kids = site;
|
||||
site->kids = NULL;
|
||||
|
||||
mkey = (const void*) event.u.site.method;
|
||||
mhash = hash_serial(mkey);
|
||||
meth = (tmgraphnode*)
|
||||
*PL_HashTableRawLookup(tmr->methods, mhash, mkey);
|
||||
site->method = meth;
|
||||
site->offset = event.u.site.offset;
|
||||
site->allocs.bytes.direct = site->allocs.bytes.total = 0;
|
||||
site->allocs.calls.direct = site->allocs.calls.total = 0;
|
||||
site->frees.bytes.direct = site->frees.bytes.total = 0;
|
||||
site->frees.calls.direct = site->frees.calls.total = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case TM_EVENT_MALLOC:
|
||||
case TM_EVENT_CALLOC:
|
||||
case TM_EVENT_REALLOC: {
|
||||
tmcallsite *site;
|
||||
uint32 size, oldsize;
|
||||
double delta, sqdelta, sqszdelta;
|
||||
tmgraphnode *meth, *comp, *lib;
|
||||
|
||||
site = tmreader_callsite(tmr, event.serial);
|
||||
if (!site) {
|
||||
fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n",
|
||||
tmr->program, event.type, (unsigned long) event.serial);
|
||||
continue;
|
||||
}
|
||||
|
||||
size = event.u.alloc.size;
|
||||
oldsize = event.u.alloc.oldsize;
|
||||
delta = (double)size - (double)oldsize;
|
||||
site->allocs.bytes.direct += delta;
|
||||
if (event.type != TM_EVENT_REALLOC)
|
||||
site->allocs.calls.direct++;
|
||||
meth = site->method;
|
||||
if (meth) {
|
||||
meth->allocs.bytes.direct += delta;
|
||||
sqdelta = delta * delta;
|
||||
if (event.type == TM_EVENT_REALLOC) {
|
||||
sqszdelta = ((double)size * size)
|
||||
- ((double)oldsize * oldsize);
|
||||
meth->sqsum += sqszdelta;
|
||||
} else {
|
||||
meth->sqsum += sqdelta;
|
||||
meth->allocs.calls.direct++;
|
||||
}
|
||||
comp = meth->up;
|
||||
if (comp) {
|
||||
comp->allocs.bytes.direct += delta;
|
||||
if (event.type == TM_EVENT_REALLOC) {
|
||||
comp->sqsum += sqszdelta;
|
||||
} else {
|
||||
comp->sqsum += sqdelta;
|
||||
comp->allocs.calls.direct++;
|
||||
}
|
||||
lib = comp->up;
|
||||
if (lib) {
|
||||
lib->allocs.bytes.direct += delta;
|
||||
if (event.type == TM_EVENT_REALLOC) {
|
||||
lib->sqsum += sqszdelta;
|
||||
} else {
|
||||
lib->sqsum += sqdelta;
|
||||
lib->allocs.calls.direct++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TM_EVENT_FREE: {
|
||||
tmcallsite *site;
|
||||
uint32 size;
|
||||
tmgraphnode *meth, *comp, *lib;
|
||||
|
||||
site = tmreader_callsite(tmr, event.serial);
|
||||
if (!site) {
|
||||
fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n",
|
||||
tmr->program, event.type, (unsigned long) event.serial);
|
||||
continue;
|
||||
}
|
||||
size = event.u.alloc.size;
|
||||
site->frees.bytes.direct += size;
|
||||
site->frees.calls.direct++;
|
||||
meth = site->method;
|
||||
if (meth) {
|
||||
meth->frees.bytes.direct += size;
|
||||
meth->frees.calls.direct++;
|
||||
comp = meth->up;
|
||||
if (comp) {
|
||||
comp->frees.bytes.direct += size;
|
||||
comp->frees.calls.direct++;
|
||||
lib = comp->up;
|
||||
if (lib) {
|
||||
lib->frees.bytes.direct += size;
|
||||
lib->frees.calls.direct++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TM_EVENT_STATS:
|
||||
break;
|
||||
}
|
||||
|
||||
eventhandler(tmr, &event);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
tmgraphnode *tmreader_library(tmreader *tmr, uint32 serial)
|
||||
{
|
||||
const void *key;
|
||||
PLHashNumber hash;
|
||||
|
||||
key = (const void*) serial;
|
||||
hash = hash_serial(key);
|
||||
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->libraries, hash, key);
|
||||
}
|
||||
|
||||
tmgraphnode *tmreader_component(tmreader *tmr, const char *name)
|
||||
{
|
||||
PLHashNumber hash;
|
||||
|
||||
hash = PL_HashString(name);
|
||||
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->components, hash, name);
|
||||
}
|
||||
|
||||
tmgraphnode *tmreader_method(tmreader *tmr, uint32 serial)
|
||||
{
|
||||
const void *key;
|
||||
PLHashNumber hash;
|
||||
|
||||
key = (const void*) serial;
|
||||
hash = hash_serial(key);
|
||||
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->methods, hash, key);
|
||||
}
|
||||
|
||||
tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial)
|
||||
{
|
||||
const void *key;
|
||||
PLHashNumber hash;
|
||||
|
||||
key = (const void*) serial;
|
||||
hash = hash_serial(key);
|
||||
return (tmcallsite*) *PL_HashTableRawLookup(tmr->callsites, hash, key);
|
||||
}
|
||||
|
||||
int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to, tmcallsite *site)
|
||||
{
|
||||
tmgraphlink *outlink;
|
||||
tmgraphedge *edge;
|
||||
|
||||
for (outlink = from->out; outlink; outlink = outlink->next) {
|
||||
if (outlink->node == to) {
|
||||
/*
|
||||
* Say the stack looks like this: ... => JS => js => JS => js.
|
||||
* We must avoid overcounting JS=>js because the first edge total
|
||||
* includes the second JS=>js edge's total (which is because the
|
||||
* lower site's total includes all its kids' totals).
|
||||
*/
|
||||
edge = TM_LINK_TO_EDGE(outlink, TM_EDGE_OUT_LINK);
|
||||
if (!to->low || to->low < from->low) {
|
||||
/* Add the direct and total counts to edge->allocs. */
|
||||
edge->allocs.bytes.direct += site->allocs.bytes.direct;
|
||||
edge->allocs.bytes.total += site->allocs.bytes.total;
|
||||
edge->allocs.calls.direct += site->allocs.calls.direct;
|
||||
edge->allocs.calls.total += site->allocs.calls.total;
|
||||
|
||||
/* Now update the free counts. */
|
||||
edge->frees.bytes.direct += site->frees.bytes.direct;
|
||||
edge->frees.bytes.total += site->frees.bytes.total;
|
||||
edge->frees.calls.direct += site->frees.calls.direct;
|
||||
edge->frees.calls.total += site->frees.calls.total;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
edge = (tmgraphedge*) malloc(sizeof(tmgraphedge));
|
||||
if (!edge)
|
||||
return 0;
|
||||
edge->links[TM_EDGE_OUT_LINK].node = to;
|
||||
edge->links[TM_EDGE_OUT_LINK].next = from->out;
|
||||
from->out = &edge->links[TM_EDGE_OUT_LINK];
|
||||
edge->links[TM_EDGE_IN_LINK].node = from;
|
||||
edge->links[TM_EDGE_IN_LINK].next = to->in;
|
||||
to->in = &edge->links[TM_EDGE_IN_LINK];
|
||||
edge->allocs = site->allocs;
|
||||
edge->frees = site->frees;
|
||||
return 1;
|
||||
}
|
||||
192
mozilla/tools/trace-malloc/tmreader.h
Normal file
192
mozilla/tools/trace-malloc/tmreader.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is tmreader.h/tmreader.c code, released
|
||||
* July 7, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich, 7-July-2000
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the MPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the MPL or the GPL.
|
||||
*/
|
||||
#ifndef tmreader_h___
|
||||
#define tmreader_h___
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "plhash.h"
|
||||
#include "nsTraceMalloc.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct tmreader tmreader;
|
||||
typedef struct tmevent tmevent;
|
||||
typedef struct tmcounts tmcounts;
|
||||
typedef struct tmallcounts tmallcounts;
|
||||
typedef struct tmgraphlink tmgraphlink;
|
||||
typedef struct tmgraphedge tmgraphedge;
|
||||
typedef struct tmgraphnode tmgraphnode;
|
||||
typedef struct tmcallsite tmcallsite;
|
||||
|
||||
struct tmevent {
|
||||
char type;
|
||||
uint32 serial;
|
||||
union {
|
||||
char *libname;
|
||||
struct {
|
||||
uint32 library;
|
||||
char *name;
|
||||
} method;
|
||||
struct {
|
||||
uint32 parent;
|
||||
uint32 method;
|
||||
uint32 offset;
|
||||
} site;
|
||||
struct {
|
||||
uint32 oldsize;
|
||||
uint32 size;
|
||||
} alloc;
|
||||
struct {
|
||||
nsTMStats tmstats;
|
||||
uint32 calltree_maxkids_parent;
|
||||
uint32 calltree_maxstack_top;
|
||||
} stats;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct tmcounts {
|
||||
uint32 direct; /* things allocated by this node's code */
|
||||
uint32 total; /* direct + things from all descendents */
|
||||
};
|
||||
|
||||
struct tmallcounts {
|
||||
tmcounts bytes;
|
||||
tmcounts calls;
|
||||
};
|
||||
|
||||
struct tmgraphnode {
|
||||
PLHashEntry entry; /* key is serial or name, value must be name */
|
||||
tmgraphlink *in;
|
||||
tmgraphlink *out;
|
||||
tmgraphnode *up; /* parent in supergraph, e.g., JS for JS_*() */
|
||||
tmgraphnode *down; /* subgraph kids, declining bytes.total order */
|
||||
tmgraphnode *next; /* next kid in supergraph node's down list */
|
||||
int low; /* 0 or lowest current tree walk level */
|
||||
tmallcounts allocs;
|
||||
tmallcounts frees;
|
||||
double sqsum; /* sum of squared bytes.direct */
|
||||
int sort; /* sorted index in node table, -1 if no table */
|
||||
};
|
||||
|
||||
#define tmgraphnode_name(node) ((char*) (node)->entry.value)
|
||||
|
||||
#define tmlibrary_serial(lib) ((uint32) (lib)->entry.key)
|
||||
#define tmcomponent_name(comp) ((const char*) (comp)->entry.key)
|
||||
|
||||
/* Half a graphedge, not including per-edge allocation stats. */
|
||||
struct tmgraphlink {
|
||||
tmgraphlink *next; /* next fanning out from or into a node */
|
||||
tmgraphnode *node; /* the other node (to if OUT, from if IN) */
|
||||
};
|
||||
|
||||
/*
|
||||
* It's safe to downcast a "from" tmgraphlink (one linked from a node's out
|
||||
* pointer) to tmgraphedge. To go from an "out" (linked via tmgraphedge.from)
|
||||
* or "in" (linked via tmgraphedge.to) list link to its containing edge, use
|
||||
* TM_LINK_TO_EDGE(link, which).
|
||||
*/
|
||||
struct tmgraphedge {
|
||||
tmgraphlink links[2];
|
||||
tmallcounts allocs;
|
||||
tmallcounts frees;
|
||||
};
|
||||
|
||||
/* Indices into tmgraphedge.links -- out must come first. */
|
||||
#define TM_EDGE_OUT_LINK 0
|
||||
#define TM_EDGE_IN_LINK 1
|
||||
|
||||
#define TM_LINK_TO_EDGE(link,which) ((tmgraphedge*) &(link)[-(which)])
|
||||
|
||||
struct tmcallsite {
|
||||
PLHashEntry entry; /* key is site serial number */
|
||||
tmcallsite *parent; /* calling site */
|
||||
tmcallsite *siblings; /* other sites reached from parent */
|
||||
tmcallsite *kids; /* sites reached from here */
|
||||
tmgraphnode *method; /* method node in tmr->methods graph */
|
||||
uint32 offset; /* pc offset from start of method */
|
||||
tmallcounts allocs;
|
||||
tmallcounts frees;
|
||||
};
|
||||
|
||||
struct tmreader {
|
||||
const char *program;
|
||||
void *data;
|
||||
PLHashTable *libraries;
|
||||
PLHashTable *components;
|
||||
PLHashTable *methods;
|
||||
PLHashTable *callsites;
|
||||
tmcallsite calltree_root;
|
||||
};
|
||||
|
||||
typedef void (*tmeventhandler)(tmreader *tmr, tmevent *event);
|
||||
|
||||
/* The tmreader constructor and destructor. */
|
||||
extern tmreader *tmreader_new(const char *program, void *data);
|
||||
extern void tmreader_destroy(tmreader *tmr);
|
||||
|
||||
/*
|
||||
* Return -1 on permanent fatal error, 0 if filename can't be opened or is not
|
||||
* a trace-malloc logfile, and 1 on success.
|
||||
*/
|
||||
extern int tmreader_eventloop(tmreader *tmr, const char *filename,
|
||||
tmeventhandler eventhandler);
|
||||
|
||||
/* Map serial number or name to graphnode or callsite. */
|
||||
extern tmgraphnode *tmreader_library(tmreader *tmr, uint32 serial);
|
||||
extern tmgraphnode *tmreader_component(tmreader *tmr, const char *name);
|
||||
extern tmgraphnode *tmreader_method(tmreader *tmr, uint32 serial);
|
||||
extern tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial);
|
||||
|
||||
/*
|
||||
* Connect node 'from' to node 'to' with an edge, if there isn't one already
|
||||
* connecting the nodes. Add site's allocation stats to the edge only if we
|
||||
* create the edge, or if we find that it exists, but that to->low is zero or
|
||||
* less than from->low.
|
||||
*
|
||||
* If the callsite tree already totals allocation costs (tmcounts.total for
|
||||
* each site includes tmcounts.direct for that site, plus tmcounts.total for
|
||||
* all kid sites), then the node->low watermarks should be set from the tree
|
||||
* level when walking the callsite tree, and should be set to non-zero values
|
||||
* only if zero (the root is at level 0). A low watermark should be cleared
|
||||
* when the tree walk unwinds past the level at which it was set non-zero.
|
||||
*
|
||||
* Return 0 on error (malloc failure) and 1 on success.
|
||||
*/
|
||||
extern int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to,
|
||||
tmcallsite *site);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* tmreader_h___ */
|
||||
@@ -1,5 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
</IfModule>
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_controller.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* This file is application-wide controller file. You can put all
|
||||
* application-wide controller-related methods here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your controllers
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
*/
|
||||
|
||||
uses('Sanitize');
|
||||
|
||||
class AppController extends Controller {
|
||||
|
||||
/**
|
||||
* This function is intended to be used with url parameters when passing them to
|
||||
* a view. (This is useful when echoing values out in <input> tags, etc.
|
||||
* Note that the keys to the arrays are escaped as well.
|
||||
*
|
||||
* @param array dirty parameters
|
||||
* @return array cleaned values
|
||||
*/
|
||||
function decodeAndSanitize($params)
|
||||
{
|
||||
$clean = array();
|
||||
|
||||
foreach ($params as $var => $val) {
|
||||
$var = $this->Sanitize->html(urldecode($var));
|
||||
$val = $this->Sanitize->html(urldecode($val));
|
||||
|
||||
$clean[$var] = $val;
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_model.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* This file is application-wide model file. You can put all
|
||||
* application-wide model-related methods here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your models
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
*/
|
||||
|
||||
uses('sanitize');
|
||||
|
||||
class AppModel extends Model {
|
||||
|
||||
/**
|
||||
* Will clean arrays for input into SQL.
|
||||
* Note that the array keys are getting cleaned here as well. If you're using strings
|
||||
* (with escapable characters in them) as keys to your array, be extra careful.
|
||||
*
|
||||
* @access public
|
||||
* @param array to be cleaned
|
||||
* @return array with sql escaped
|
||||
*/
|
||||
function cleanArrayForSql($array)
|
||||
{
|
||||
$sanitize = new Sanitize();
|
||||
$clean = array();
|
||||
|
||||
foreach ($array as $var => $val)
|
||||
{
|
||||
$var = $sanitize->sql($var);
|
||||
$val = $sanitize->sql($val);
|
||||
$clean[$var] = $val;
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,76 +0,0 @@
|
||||
;<?php die() ?>
|
||||
; SVN FILE: $Id: acl.ini.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $
|
||||
;/**
|
||||
; * Short description for file.
|
||||
; *
|
||||
; *
|
||||
; * PHP versions 4 and 5
|
||||
; *
|
||||
; * CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
; * Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * 1785 E. Sahara Avenue, Suite 490-204
|
||||
; * Las Vegas, Nevada 89104
|
||||
; *
|
||||
; * Licensed under The MIT License
|
||||
; * Redistributions of files must retain the above copyright notice.
|
||||
; *
|
||||
; * @filesource
|
||||
; * @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
; * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
; * @package cake
|
||||
; * @subpackage cake.app.config
|
||||
; * @since CakePHP v 0.10.0.1076
|
||||
; * @version $Revision: 1.1.1.1 $
|
||||
; * @modifiedby $LastChangedBy: phpnut $
|
||||
; * @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
; * @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
; */
|
||||
|
||||
; acl.ini.php - Cake ACL Configuration
|
||||
; ---------------------------------------------------------------------
|
||||
; Use this file to specify user permissions.
|
||||
; aco = access control object (something in your application)
|
||||
; aro = access request object (something requesting access)
|
||||
;
|
||||
; User records are added as follows:
|
||||
;
|
||||
; [uid]
|
||||
; groups = group1, group2, group3
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; Group records are added in a similar manner:
|
||||
;
|
||||
; [gid]
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; The allow, deny, and groups sections are all optional.
|
||||
; NOTE: groups names *cannot* ever be the same as usernames!
|
||||
;
|
||||
; ACL permissions are checked in the following order:
|
||||
; 1. Check for user denies (and DENY if specified)
|
||||
; 2. Check for user allows (and ALLOW if specified)
|
||||
; 3. Gather user's groups
|
||||
; 4. Check group denies (and DENY if specified)
|
||||
; 5. Check group allows (and ALLOW if specified)
|
||||
; 6. If no aro, aco, or group information is found, DENY
|
||||
;
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
;-------------------------------------
|
||||
;Users
|
||||
;-------------------------------------
|
||||
|
||||
[username-goes-here]
|
||||
groups = group1, group2
|
||||
deny = aco1, aco2
|
||||
allow = aco3, aco4
|
||||
|
||||
;-------------------------------------
|
||||
;Groups
|
||||
;-------------------------------------
|
||||
|
||||
[groupname-goes-here]
|
||||
deny = aco5, aco6
|
||||
allow = aco7, aco8
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: bootstrap.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.10.8.2117
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php is loaded
|
||||
* This is an application wide file to load any function that is not used within a class define.
|
||||
* You can also use this to include or require any files in your application.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The settings below can be used to set additional paths to models, views and controllers.
|
||||
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
|
||||
*
|
||||
* $modelPaths = array('full path to models', 'second full path to models', 'etc...');
|
||||
* $viewPaths = array('this path to views', 'second full path to views', 'etc...');
|
||||
* $controllerPaths = array('this path to controllers', 'second full path to controllers', 'etc...');
|
||||
*
|
||||
*/
|
||||
|
||||
//EOF
|
||||
?>
|
||||
@@ -1,153 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: core.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behaviour ofCake.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* If you do not have mod rewrite on your system
|
||||
* or if you prefer to use CakePHP pretty urls.
|
||||
* uncomment the line below.
|
||||
* Note: If you do have mod rewrite but prefer the
|
||||
* CakePHP pretty urls, you also have to remove the
|
||||
* .htaccess files
|
||||
* release/.htaccess
|
||||
* release/app/.htaccess
|
||||
* release/app/webroot/.htaccess
|
||||
*/
|
||||
//define ('BASE_URL', env('SCRIPT_NAME'));
|
||||
|
||||
/**
|
||||
* Set debug level here:
|
||||
* - 0: production
|
||||
* - 1: development
|
||||
* - 2: full debug with sql
|
||||
* - 3: full debug with sql and dump of the current object
|
||||
*
|
||||
* In production, the "flash messages" redirect after a time interval.
|
||||
* With the other debug levels you get to click the "flash message" to continue.
|
||||
*
|
||||
*/
|
||||
define('DEBUG', 0);
|
||||
/**
|
||||
* Turn of caching checking wide.
|
||||
* You must still use the controller var cacheAction inside you controller class.
|
||||
* You can either set it controller wide, or in each controller method.
|
||||
* use var $cacheAction = true; or in the controller method $this->cacheAction = true;
|
||||
*/
|
||||
define ('CACHE_CHECK', false);
|
||||
/**
|
||||
* Error constant. Used for differentiating error logging and debugging.
|
||||
* Currently PHP supports LOG_DEBUG
|
||||
*/
|
||||
define ('LOG_ERROR', 2);
|
||||
/**
|
||||
* CakePHP includes 3 types of session saves
|
||||
* database or file. Set this to your preferred method.
|
||||
* If you want to use your own save handler place it in
|
||||
* app/config/name.php DO NOT USE file or database as the name.
|
||||
* and use just the name portion below.
|
||||
*
|
||||
* Setting this to cake will save files to /cakedistro/tmp directory
|
||||
* Setting it to php will use the php default save path
|
||||
* Setting it to database will use the database
|
||||
*
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_SAVE', 'php');
|
||||
/**
|
||||
* Set a random string of used in session.
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_STRING', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
|
||||
/**
|
||||
* Set the name of session cookie
|
||||
*
|
||||
*/
|
||||
define('CAKE_SESSION_COOKIE', 'CAKEPHP');
|
||||
|
||||
/**
|
||||
* Set level of Cake security.
|
||||
*
|
||||
*/
|
||||
define('CAKE_SECURITY', 'high');
|
||||
|
||||
/**
|
||||
* Set Cake Session time out.
|
||||
* If CAKE_SECURITY define is set
|
||||
* high: multiplied by 10
|
||||
* medium: is multiplied by 100
|
||||
* low is: multiplied by 300
|
||||
*
|
||||
* Number below is seconds.
|
||||
*/
|
||||
define('CAKE_SESSION_TIMEOUT', '120');
|
||||
|
||||
/**
|
||||
* Uncomment the define below to use cake built in admin routes.
|
||||
* You can set this value to anything you want.
|
||||
* All methods related to the admin route should be prefixed with the
|
||||
* name you set CAKE_ADMIN to.
|
||||
* For example: admin_index, admin_edit
|
||||
*/
|
||||
//define('CAKE_ADMIN', 'admin');
|
||||
|
||||
/**
|
||||
* The define below is used to turn cake built webservices
|
||||
* on or off. Default setting is off.
|
||||
*/
|
||||
define('WEBSERVICES', 'off');
|
||||
|
||||
/**
|
||||
* Compress output CSS (removing comments, whitespace, repeating tags etc.)
|
||||
* This requires a/var/cache directory to be writable by the web server (caching).
|
||||
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use Controller::cssTag().
|
||||
*/
|
||||
define('COMPRESS_CSS', false);
|
||||
|
||||
/**
|
||||
* If set to true, helpers would output data instead of returning it.
|
||||
*/
|
||||
define('AUTO_OUTPUT', false);
|
||||
|
||||
/**
|
||||
* If set to false, session would not automatically be started.
|
||||
*/
|
||||
define('AUTO_SESSION', true);
|
||||
|
||||
/**
|
||||
* Set the max size of file to use md5() .
|
||||
*/
|
||||
define('MAX_MD5SIZE', (5*1024)*1024 );
|
||||
|
||||
/**
|
||||
* To use Access Control Lists with Cake...
|
||||
*/
|
||||
define('ACL_CLASSNAME', 'DB_ACL');
|
||||
define('ACL_FILENAME', 'dbacl'.DS.'db_acl');
|
||||
|
||||
?>
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: database.php.default,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behaviour ofCake.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* In this file you set up your database connection details.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.config
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Database configuration class.
|
||||
* You can specify multiple configurations for production, development and testing.
|
||||
*
|
||||
* driver =>
|
||||
* mysql, postgres, sqlite, adodb-drivername, pear-drivername
|
||||
*
|
||||
* connect =>
|
||||
* MySQL set the connect to either mysql_pconnect of mysql_connect
|
||||
* PostgreSQL set the connect to either pg_pconnect of pg_connect
|
||||
* SQLite set the connect to sqlite_popen sqlite_open
|
||||
* ADOdb set the connect to one of these
|
||||
* (http://phplens.com/adodb/supported.databases.html) and
|
||||
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
|
||||
*
|
||||
* host =>
|
||||
* the host you connect to the database
|
||||
* MySQL 'localhost' to add a port number use 'localhost:port#'
|
||||
* PostgreSQL 'localhost' to add a port number use 'localhost port=5432'
|
||||
*
|
||||
*/
|
||||
class DATABASE_CONFIG
|
||||
{
|
||||
var $default = array('driver' => 'mysql',
|
||||
'connect' => 'mysql_connect',
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'project_name',
|
||||
'prefix' => '');
|
||||
|
||||
var $test = array('driver' => 'mysql',
|
||||
'connect' => 'mysql_connect',
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'project_name-test',
|
||||
'prefix' => '');
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: inflections.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Custom Inflected Words.
|
||||
*
|
||||
* This file is used to hold words that are not matched in the normail Inflector::pluralize() and
|
||||
* Inflector::singularize()
|
||||
*
|
||||
* PHP versions 4 and %
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 1.0.0.2312
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice');
|
||||
*/
|
||||
$pluralRules = array();
|
||||
/**
|
||||
* This is a key only array of plural words that should not be inflected.
|
||||
* Notice the last comma
|
||||
*
|
||||
* $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox');
|
||||
*/
|
||||
$uninflectedPlural = array();
|
||||
/**
|
||||
* This is a key => value array of plural irregular words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers')
|
||||
*/
|
||||
$irregularPlural = array();
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i')
|
||||
*/
|
||||
$singularRules = array();
|
||||
/**
|
||||
* This is a key only array of singular words that should not be inflected.
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
* as the $uninflectedPlural above.
|
||||
*/
|
||||
$uninflectedSingular = $uninflectedPlural;
|
||||
/**
|
||||
* This is a key => value array of singular irregular words.
|
||||
* Most of the time this will be a reverse of the above $irregularPlural array
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
*
|
||||
* $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother')
|
||||
*/
|
||||
$irregularSingular = array_flip($irregularPlural);
|
||||
?>
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: routes.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* In this file, you set up routes to your controllers and their actions.
|
||||
* Routes are very important mechanism that allows you to freely connect
|
||||
* different urls to chosen controllers and their actions (functions).
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.config
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Here, we are connecting '/' (base path) to controller called 'Pages',
|
||||
* its action called 'display', and we pass a param to select the view file
|
||||
* to use (in this case, /app/views/pages/home.thtml)...
|
||||
*/
|
||||
$Route->connect ('/', array('controller'=>'results', 'action'=>'', ''));
|
||||
|
||||
/**
|
||||
* ...and connect the rest of 'Pages' controller's urls.
|
||||
*/
|
||||
$Route->connect ('/pages/*', array('controller'=>'pages', 'action'=>'display'));
|
||||
|
||||
/**
|
||||
* Then we connect url '/test' to our test controller. This is helpfull in
|
||||
* developement.
|
||||
*/
|
||||
$Route->connect ('/tests', array('controller'=>'tests', 'action'=>'index'));
|
||||
|
||||
?>
|
||||
@@ -1,30 +0,0 @@
|
||||
CREATE TABLE `acos` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`model` varchar(255) NOT NULL default '',
|
||||
`object_id` int(11) default NULL,
|
||||
`alias` varchar(255) NOT NULL default '',
|
||||
`lft` int(11) default NULL,
|
||||
`rght` int(11) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `aros` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`model` varchar(255) NOT NULL default '',
|
||||
`user_id` int(11) default NULL,
|
||||
`alias` varchar(255) NOT NULL default '',
|
||||
`lft` int(11) default NULL,
|
||||
`rght` int(11) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `aros_acos` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`aro_id` int(11) default NULL,
|
||||
`aco_id` int(11) default NULL,
|
||||
`_create` int(1) NOT NULL default '0',
|
||||
`_read` int(1) NOT NULL default '0',
|
||||
`_update` int(1) NOT NULL default '0',
|
||||
`_delete` int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
@@ -1,11 +0,0 @@
|
||||
-- @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
-- @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
-- @since CakePHP v 0.10.8.1997
|
||||
-- @version $Revision: 1.1.1.1 $
|
||||
|
||||
CREATE TABLE cake_sessions (
|
||||
id varchar(255) NOT NULL default '',
|
||||
data text,
|
||||
expires int(11) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class ApplicationsController extends AppController {
|
||||
|
||||
var $name = 'Applications';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class IntentionsController extends AppController {
|
||||
|
||||
var $name = 'Intentions';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
class IssuesController extends AppController {
|
||||
|
||||
var $name = 'Issues';
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* Include the CSV library. It would be nice to make this OO sometime */
|
||||
vendor('csv/csv');
|
||||
|
||||
class ResultsController extends AppController {
|
||||
|
||||
var $name = 'Results';
|
||||
|
||||
/**
|
||||
* Model's this controller uses
|
||||
* @var array
|
||||
*/
|
||||
var $uses = array('Application','Result');
|
||||
|
||||
/**
|
||||
* Cake Helpers
|
||||
* @var array
|
||||
*/
|
||||
var $helpers = array('Html', 'Javascript', 'Export', 'Pagination','Time');
|
||||
|
||||
/**
|
||||
* Pagination helper variable array
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
var $pagination_parameters = array();
|
||||
|
||||
/**
|
||||
* Will hold a sanitize object
|
||||
* @var object
|
||||
*/
|
||||
var $Sanitize;
|
||||
|
||||
/**
|
||||
* Constructor - sets up the sanitizer and the pagination
|
||||
*/
|
||||
function ResultsController()
|
||||
{
|
||||
parent::AppController();
|
||||
|
||||
$this->Sanitize = new Sanitize();
|
||||
|
||||
// Pagination Stuff
|
||||
$this->pagination_parameters['show'] = empty($_GET['show'])? '10' : $this->Sanitize->paranoid($_GET['show']);
|
||||
$this->pagination_parameters['sortBy'] = empty($_GET['sort'])? 'created' : $this->Sanitize->paranoid($_GET['sort']);
|
||||
$this->pagination_parameters['direction'] = empty($_GET['direction'])? 'desc': $this->Sanitize->paranoid($_GET['direction']);
|
||||
$this->pagination_parameters['page'] = empty($_GET['page'])? '1': $this->Sanitize->paranoid($_GET['page']);
|
||||
$this->pagination_parameters['order'] = $this->modelClass.'.'.$this->pagination_parameters['sortBy'].' '.strtoupper($this->pagination_parameters['direction']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Front page will show the graph
|
||||
*/
|
||||
function index()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->getApplications());
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// We'll need to include the graphing libraries
|
||||
$this->set('include_graph_libraries', true);
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('descriptionAndTotalsData',$this->Result->getDescriptionAndTotalsData($this->params['url']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a table of user comments
|
||||
*/
|
||||
function comments()
|
||||
{
|
||||
// Products dropdown
|
||||
$this->set('products', $this->Application->getApplications());
|
||||
|
||||
// Fill in all the data passed in $_GET
|
||||
$this->set('url_params',$this->decodeAndSanitize($this->params['url']));
|
||||
|
||||
// Pagination settings
|
||||
$paging['style'] = 'html';
|
||||
$paging['link'] = "/results/comments/?product=".urlencode($this->params['url']['product'])."&start_date=".urlencode($this->params['url']['start_date'])."&end_date=".urlencode($this->params['url']['end_date'])."&show={$this->pagination_parameters['show']}&sort={$this->pagination_parameters['sortBy']}&direction={$this->pagination_parameters['direction']}&page=";
|
||||
$paging['count'] = $this->Result->getCommentCount($this->params['url']);
|
||||
$paging['page'] = $this->pagination_parameters['page'];
|
||||
$paging['limit'] = $this->pagination_parameters['show'];
|
||||
$paging['show'] = array('10','25','50');
|
||||
|
||||
// No point in showing them an error if they click on "show 50" but they are
|
||||
// already on the last page.
|
||||
if ($paging['count'] < ($this->pagination_parameters['page'] * ($this->pagination_parameters['show']/2))) {
|
||||
$this->pagination_parameters['page'] = $paging['page'] = 1;
|
||||
}
|
||||
|
||||
// Set pagination array
|
||||
$this->set('paging',$paging);
|
||||
|
||||
// Core data to show on page
|
||||
$this->set('commentsData',$this->Result->getComments($this->params['url'], $this->pagination_parameters));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a csv
|
||||
*/
|
||||
function csv()
|
||||
{
|
||||
// Get rid of the header/footer/etc.
|
||||
$this->layout = null;
|
||||
|
||||
// Our CSV library sends headers and everything. Keep the view empty!
|
||||
csv_send_csv($this->Result->getCsvExportData($this->params['url']));
|
||||
|
||||
// I'm not exiting here in case someone is going to use post callback stuff.
|
||||
// In development, that means extra lines get added to our CSVs, but in
|
||||
// production it should be clean.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: index.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app
|
||||
* @since CakePHP v 0.10.0.1076
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
require 'webroot'.DIRECTORY_SEPARATOR.'index.php';
|
||||
?>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
class Application extends AppModel {
|
||||
var $name = 'Application';
|
||||
|
||||
var $hasOne = array('Result');
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Intention' => array('className' => 'Intention'),
|
||||
'Issue' => array('className' => 'Issue')
|
||||
);
|
||||
|
||||
/**
|
||||
* This was added because running findAll() on this model does a left join on the
|
||||
* results table which takes around 10 seconds to grab all the data. All I want
|
||||
* is a list of the applications...
|
||||
*
|
||||
* @return array rows representing each application
|
||||
*/
|
||||
function getApplications()
|
||||
{
|
||||
return $this->query('SELECT * FROM `applications` ORDER BY `id`');
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
class Intention extends AppModel {
|
||||
var $name = 'Intention';
|
||||
|
||||
var $hasOne = array('Result');
|
||||
|
||||
var $hasAndBelongsToMany = array('Application' =>
|
||||
array('className' => 'Application')
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
class Issue extends AppModel {
|
||||
var $name = 'Issue';
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Application' => array('className' => 'Application'),
|
||||
'Result' => array('className' => 'Result')
|
||||
);
|
||||
}
|
||||
?>
|
||||
@@ -1,339 +0,0 @@
|
||||
<?php
|
||||
class Result extends AppModel {
|
||||
var $name = 'Result';
|
||||
|
||||
var $belongsTo = array('Application', 'Intention');
|
||||
|
||||
var $hasAndBelongsToMany = array('Issue' =>
|
||||
array('className' => 'Issue')
|
||||
);
|
||||
|
||||
/**
|
||||
* Count's all the comments, according to the parameters.
|
||||
* @param array URL parameters
|
||||
* @return Cake's findCount() value
|
||||
*/
|
||||
function getCommentCount($params)
|
||||
{
|
||||
// Clean parameters
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We only want to see rows with comments
|
||||
$_conditions = array("comments NOT LIKE ''");
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` >= '{$_date}'");
|
||||
}
|
||||
}
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` <= '{$_date}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
/* Note that 'Application' is not the actual name of the table! You can
|
||||
* thank cake for that.*/
|
||||
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
|
||||
} else {
|
||||
// defaults I guess?
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
// Do the actual query
|
||||
$comments = $this->findCount($_conditions);
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will retrieve all the comments within param's and pagination's parameters
|
||||
* @param array URL parameters
|
||||
* @param array pagination values from the controller
|
||||
* @param boolean if privacy is true phone numbers and email addresses will be
|
||||
* masked
|
||||
* @return cake result set
|
||||
*/
|
||||
function getComments($params, $pagination, $privacy=true)
|
||||
{
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We only want to see rows with comments
|
||||
$_conditions = array("comments NOT LIKE ''");
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` >= '{$_date}'");
|
||||
}
|
||||
}
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
array_push($_conditions, "`created` <= '{$_date}'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
/* Note that 'Application' is not the actual name of the table! You can
|
||||
* thank cake for that.*/
|
||||
array_push($_conditions, "`Application`.`name` LIKE '%{$_product}%'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '%{$_version}%'");
|
||||
} else {
|
||||
// defaults I guess?
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
array_push($_conditions, "`Application`.`name` LIKE 'Mozilla Firefox'");
|
||||
array_push($_conditions, "`Application`.`version` LIKE '1.5'");
|
||||
}
|
||||
|
||||
$comments = $this->findAll($_conditions, null, $pagination['order'], $pagination['show'], $pagination['page']);
|
||||
|
||||
if ($privacy) {
|
||||
// Pull out all the email addresses and phone numbers
|
||||
foreach ($comments as $var => $val) {
|
||||
|
||||
// Handle foo@bar.com
|
||||
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
|
||||
$comments[$var]['Result']['comments'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['comments']);
|
||||
$comments[$var]['Result']['intention_text'] = preg_replace($_email_regex,'$1@****.$3',$comments[$var]['Result']['intention_text']);
|
||||
|
||||
// Handle xxx-xxx-xxxx
|
||||
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
|
||||
$comments[$var]['Result']['comments'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['comments']);
|
||||
$comments[$var]['Result']['intention_text'] = preg_replace($_phone_regex,'$1-****',$comments[$var]['Result']['intention_text']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function runs the query to get the export data for the CSV file.
|
||||
*
|
||||
* @param array URL parameters
|
||||
* @param boolean if privacy is true phone numbers and email addresses will be
|
||||
* masked
|
||||
* @return array two dimensional array that should be pretty easy to transform
|
||||
* into a CSV.
|
||||
*/
|
||||
function getCsvExportData($params, $privacy=true)
|
||||
{
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
// We have to use a left join here because there isn't always an intention
|
||||
$_query = "
|
||||
SELECT
|
||||
`results`.`id`,
|
||||
`results`.`created`,
|
||||
`results`.`intention_text` as `intention_other`,
|
||||
`results`.`comments`,
|
||||
`intentions`.`description` as `intention`
|
||||
FROM `results`
|
||||
LEFT JOIN `intentions` ON `results`.`intention_id`=`intentions`.`id`
|
||||
INNER JOIN `applications` ON `applications`.`id` = `results`.`application_id`
|
||||
WHERE
|
||||
1=1
|
||||
";
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` >= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` <= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
|
||||
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
|
||||
} else {
|
||||
// defaults I guess?
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
|
||||
$_query .= " ORDER BY `results`.`created` ASC";
|
||||
|
||||
$res = $this->query($_query);
|
||||
|
||||
// Since we're exporting to a CSV, we need to flatten the results into a 2
|
||||
// dimensional table array
|
||||
$newdata = array();
|
||||
|
||||
foreach ($res as $result) {
|
||||
|
||||
$newdata[] = array_merge($result['results'], $result['intentions']);
|
||||
}
|
||||
|
||||
if ($privacy) {
|
||||
// Pull out all the email addresses and phone numbers
|
||||
foreach ($newdata as $var => $val) {
|
||||
|
||||
// Handle foo@bar.com
|
||||
$_email_regex = '/\ ?(.+)?@(.+)?\.(.+)?\ ?/';
|
||||
$newdata[$var]['comments'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['comments']);
|
||||
$newdata[$var]['intention_other'] = preg_replace($_email_regex,'$1@****.$3',$newdata[$var]['intention_other']);
|
||||
|
||||
// Handle xxx-xxx-xxxx
|
||||
$_phone_regex = '/([0-9]{3})[ .-]?[0-9]{4}/';
|
||||
$newdata[$var]['comments'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['comments']);
|
||||
$newdata[$var]['intention_other'] = preg_replace($_phone_regex,'$1-****',$newdata[$var]['intention_other']);
|
||||
}
|
||||
}
|
||||
|
||||
// Our CSV library just prints out everything in order, so we have to put the
|
||||
// column labels on here ourselves
|
||||
$newdata = array_merge(array(array_keys($newdata[0])), $newdata);
|
||||
|
||||
return $newdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will retrieve the information used for graphing.
|
||||
* @param the url parameters (unescaped)
|
||||
* @return a result set
|
||||
*/
|
||||
function getDescriptionAndTotalsData($params)
|
||||
{
|
||||
// Clean parameters for inserting into SQL
|
||||
$params = $this->cleanArrayForSql($params);
|
||||
|
||||
/* It would be nice to drop something like this in the SELECT:
|
||||
*
|
||||
* CONCAT(COUNT(*)/(SELECT COUNT(*) FROM our_giant_query_all_over_again)*100,'%') AS `percentage`
|
||||
*/
|
||||
|
||||
$_query = "
|
||||
SELECT
|
||||
issues.description,
|
||||
COUNT( DISTINCT results.id ) AS total
|
||||
FROM
|
||||
issues
|
||||
LEFT JOIN
|
||||
issues_results ON issues_results.issue_id=issues.id
|
||||
LEFT JOIN results ON results.id=issues_results.result_id AND results.application_id=applications.id
|
||||
JOIN applications_issues ON applications_issues.issue_id=issues.id
|
||||
JOIN applications ON applications.id=applications_issues.application_id
|
||||
WHERE 1=1
|
||||
";
|
||||
|
||||
if (!empty($params['start_date'])) {
|
||||
$_timestamp = strtotime($params['start_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query.= " AND `results`.`created` >= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['end_date'])) {
|
||||
$_timestamp = strtotime($params['end_date']);
|
||||
|
||||
if (!($_timestamp == -1) || $_timestamp == false) {
|
||||
$_date = date('Y-m-d H:i:s', $_timestamp);//sql format
|
||||
$_query .= " AND `results`.`created` <= '{$_date}'";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['product'])) {
|
||||
// product's come in looking like:
|
||||
// Mozilla Firefox 1.5.0.1
|
||||
$_exp = explode(' ',urldecode($params['product']));
|
||||
|
||||
if(count($_exp) == 3) {
|
||||
$_product = $_exp[0].' '.$_exp[1];
|
||||
|
||||
$_version = $_exp[2];
|
||||
|
||||
$_query .= " AND `applications`.`name` LIKE '{$_product}'";
|
||||
$_query .= " AND `applications`.`version` LIKE '{$_version}'";
|
||||
} else {
|
||||
// defaults I guess?
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
} else {
|
||||
// I'm providing a default here, because otherwise all results will be
|
||||
// returned (across all applications) and that is not desired
|
||||
$_query .= " AND `applications`.`name` LIKE 'Mozilla Firefox'";
|
||||
$_query .= " AND `applications`.`version` LIKE '1.5'";
|
||||
}
|
||||
|
||||
$_query .= " GROUP BY `issues`.`description`
|
||||
ORDER BY `issues`.`description` DESC";
|
||||
|
||||
return $this->query($_query);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,188 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Functions that take a db result and export it to CSV.
|
||||
* Usage example:
|
||||
* <code>
|
||||
* if ($_GET['csv'])
|
||||
* {
|
||||
* $res=db_query("SELECT * FROM fic_courses");
|
||||
* csv_send_csv($res);
|
||||
* exit;
|
||||
* }
|
||||
* </code>
|
||||
* @package libs
|
||||
* @subpackage csv
|
||||
* @author Richard Faaberg <faabergr@onid.orst.edu>
|
||||
* @author Mike Morgan <mike.morgan@oregonstate.edu>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use a resource or two dimensional array, then send the CSV results to user.
|
||||
* @param mixed $res MySQL resource / result, or a two dimensional array
|
||||
* @param string $name name of the export file
|
||||
* @return bool true if file sent, false otherwise
|
||||
*/
|
||||
function csv_send_csv($res,$name=null)
|
||||
{
|
||||
// set name of the export file
|
||||
$filename=(is_null($name))?'export-'.date('Y-m-d').'.csv':$name.'.csv';
|
||||
// check for valid resource
|
||||
if ( is_resource($res) )
|
||||
{
|
||||
$csv=csv_export_to_csv($res);
|
||||
}
|
||||
elseif( is_array($res) && !empty($res) )
|
||||
{
|
||||
foreach ($res as $row)
|
||||
{
|
||||
if ( !is_array($row) )
|
||||
;
|
||||
else
|
||||
$csv[] = csv_array_to_csv($row)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array($csv) )
|
||||
{
|
||||
// stream csv to user
|
||||
header("Content-type: application/x-csv");
|
||||
header('Content-disposition: inline; filename="'.$filename.'"');
|
||||
header('Cache-Control: private');
|
||||
header('Pragma: public');
|
||||
foreach ($csv as $row)
|
||||
{
|
||||
echo $row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace quotes inside of a field with double quotes, which is something CSV requires.
|
||||
* @param string $string unquoted quotes
|
||||
* @return string $string quoted quotes
|
||||
*/
|
||||
function csv_fix_quotes($string)
|
||||
{
|
||||
return preg_replace('/"/','""',$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace line breaks with commas trailed by a space.
|
||||
* @param string $string string containing line breaks
|
||||
* @param string string without line breaks
|
||||
*/
|
||||
function csv_fix_line_breaks($string)
|
||||
{
|
||||
return preg_replace('/(\n\r|\r)/','\n',$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces instances of double quotes in a string with a single quote.
|
||||
* @param string $string the string to perform the replacement on
|
||||
* @return string the string with "" replaced by "
|
||||
*/
|
||||
function csv_unfix_quotes($string)
|
||||
{
|
||||
return preg_replace('/""/', '"', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place quotes outside of every field, which inherently solves space, line break issues.
|
||||
* @param string $string
|
||||
* @return string $string with quotes around it
|
||||
*/
|
||||
function csv_add_quotes($string)
|
||||
{
|
||||
return '"'.$string.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes quotes from the beginning and the end of a string.
|
||||
* @param string $string the string to remove the quotes from
|
||||
* @return string the string, sans quotes at the beginning and end
|
||||
*/
|
||||
function csv_remove_quotes($string)
|
||||
{
|
||||
$pattern = "/^\"(.*)\"$/";
|
||||
$replacement = "$1";
|
||||
return preg_replace($pattern, $replacement, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array into a CSV string with quotes around each value.
|
||||
* @param array $array
|
||||
* @return string the values in $array surrounded by quotes and separated by commas
|
||||
*/
|
||||
function csv_array_to_csv($array)
|
||||
{
|
||||
$csv_arr = array();
|
||||
foreach ($array as $value)
|
||||
{
|
||||
$csv_arr[]=csv_add_quotes(csv_fix_quotes(csv_fix_line_breaks($value)));
|
||||
}
|
||||
$csv_string=implode(',',$csv_arr);
|
||||
|
||||
return $csv_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a CSV string into an array.
|
||||
* Please use sparingly - this creates temp files
|
||||
* @param string $string the CSV string
|
||||
* @return array the elements from the CSV string in an array
|
||||
*/
|
||||
function csv_csv_to_array($string)
|
||||
{
|
||||
$return = array();
|
||||
$length = strlen($string);
|
||||
|
||||
// create a temp file and write the string to it
|
||||
$tmpfname = tempnam('/tmp', 'csvlib');
|
||||
$fh = fopen($tmpfname, 'w');
|
||||
fwrite($fh, $string);
|
||||
fclose($fh);
|
||||
|
||||
// open the file for csv parsing
|
||||
$csvh = fopen($tmpfname, 'r');
|
||||
while (($arraydata = fgetcsv($csvh, $length, ',')) !== false)
|
||||
{
|
||||
$return = array_merge($return, $arraydata);
|
||||
}
|
||||
|
||||
fclose($csvh);
|
||||
unlink($tmpfname);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a CSV file into a two dimensional array
|
||||
* It returns all the rows in the file, so if the first row are headers, you'd need to take care of that in the returned array
|
||||
* @param string $filepath the path to the csv file
|
||||
* @param string $delimiter delimiter, default to ','
|
||||
* @param string $enclosure enclosure character, default to '"'
|
||||
* @return &array the two dimensional array with the csv file content, or an empty if an error occured
|
||||
*/
|
||||
function &csv_csv_file_to_array($filepath, $delimiter=',', $enclosure='"')
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if (!file_exists($filepath) || !is_readable($filepath))
|
||||
return $return;
|
||||
|
||||
$fh =& fopen($filepath, 'r');
|
||||
$size = filesize($filepath)+1;
|
||||
|
||||
while ($data =& fgetcsv($fh, $size, $delimiter, $enclosure))
|
||||
{
|
||||
$return[] = $data;
|
||||
}
|
||||
|
||||
fclose($fh);
|
||||
|
||||
return $return;
|
||||
}
|
||||
?>
|
||||
@@ -1,11 +0,0 @@
|
||||
<div id="t_footer">
|
||||
</div>
|
||||
|
||||
<!-- t_wrapper -->
|
||||
</div>
|
||||
|
||||
<!-- t_border -->
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Mozilla Uninstall Survey Data</title>
|
||||
<meta name="author" content="Mozilla Corporation" />
|
||||
<meta name="copyright" content="Mozilla Corporation" />
|
||||
<?php echo $html->charset('UTF-8'); ?>
|
||||
<?php echo $html->css('screen'); ?>
|
||||
<?php if (isset($include_graph_libraries) && $include_graph_libraries):
|
||||
echo $javascript->link('mochikit/MochiKit.js');
|
||||
echo $javascript->link('plotkit/Base.js');
|
||||
echo $javascript->link('plotkit/Layout.js');
|
||||
echo $javascript->link('plotkit/Canvas.js');
|
||||
echo $javascript->link('plotkit/SweetCanvas.js');
|
||||
endif; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="t_border">
|
||||
<div id="t_wrapper">
|
||||
<a class="skipnav" href="#t_content">Skip Navigation Links</a>
|
||||
<div id="t_header">
|
||||
<div id="t_title">
|
||||
<h1>Mozilla Firefox Uninstall Survey Data</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<div id="t_nav">
|
||||
<ul>
|
||||
<li><?php echo $html->link('Results', '/results'); ?></li>
|
||||
<li><?php echo $html->link('Comments', '/results/comments'); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* When we're exporting data, we end up having to pass all the parameters
|
||||
* via $_GET. Since we're doing this a few times per page (each graph, and the
|
||||
* export hrefs) this helper should make that easier.
|
||||
*/
|
||||
class ExportHelper
|
||||
{
|
||||
/**
|
||||
* Method to collect the current $_GET parameters and build another string from
|
||||
* them.
|
||||
*
|
||||
* @param string cake URL that you want prepended to the result. eg: reports/graph/
|
||||
* @param array the array of GET variables to add. These need to be
|
||||
* pre-sanitized to print in html! This is designed to
|
||||
* be used from the calling controller like:
|
||||
* $params = $this->sanitize->html($url_parameters);
|
||||
* @param string string to put between url and arguments (probably either '?' or
|
||||
* '&')
|
||||
* @param array array of strings which will be ignored
|
||||
* @return string string with the url variables appeneded to it
|
||||
*/
|
||||
function buildUrlString($url, $params, $seperator='?', $ignore=array('url'))
|
||||
{
|
||||
$arguments = '';
|
||||
|
||||
foreach ($params as $var => $val) {
|
||||
if (!in_array($var, $ignore)) {
|
||||
$arguments .= empty($arguments) ? "{$var}={$val}" : "&{$var}={$val}";
|
||||
}
|
||||
}
|
||||
|
||||
return "{$url}{$seperator}{$arguments}";
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
class PaginationHelper {
|
||||
|
||||
var $helpers = array('Html','Ajax');
|
||||
var $_pageDetails = array();
|
||||
var $link = '';
|
||||
var $show = array();
|
||||
var $page;
|
||||
var $style;
|
||||
|
||||
/**
|
||||
* Sets the default pagination options.
|
||||
*
|
||||
* @param array $paging an array detailing the page options
|
||||
*/
|
||||
function setPaging($paging)
|
||||
{
|
||||
if(!empty($paging))
|
||||
{
|
||||
|
||||
$this->link = $paging['link'];
|
||||
$this->show = $paging['show'];
|
||||
$this->page = $paging['page'];
|
||||
$this->style = $paging['style'];
|
||||
|
||||
$pageCount = ceil($paging['count'] / $paging['limit'] );
|
||||
|
||||
$this->_pageDetails = array(
|
||||
'page'=>$paging['page'],
|
||||
'recordCount'=>$paging['count'],
|
||||
'pageCount' =>$pageCount,
|
||||
'nextPage'=> ($paging['page'] < $pageCount) ? $paging['page']+1 : '',
|
||||
'previousPage'=> ($paging['page']>1) ? $paging['page']-1 : '',
|
||||
'limit'=>$paging['limit']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays limits for the query
|
||||
*
|
||||
* @param string $text - text to display before limits
|
||||
* @param string $separator - display a separate between limits
|
||||
*
|
||||
**/
|
||||
function show($text=null, $separator=null)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
$t = '';
|
||||
if(is_array($this->show))
|
||||
{
|
||||
$t = $text.$separator;
|
||||
foreach($this->show as $value)
|
||||
{
|
||||
$link = preg_replace('/show=(.*?)&/','show='.$value.'&',$this->link);
|
||||
if($this->_pageDetails['limit'] == $value)
|
||||
{
|
||||
$t .= '<em>'.$value.'</em>'.$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t .= $this->Ajax->linkToRemote($value, array("fallback"=>$this->action."#","url" => $link.$this->_pageDetails['page'],"update" => "ajax_update","method"=>"get")).$separator;
|
||||
}
|
||||
else
|
||||
{
|
||||
$t .= $this->Html->link($value,$link.$this->_pageDetails['page']).$separator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
/**
|
||||
* Displays current result information
|
||||
*
|
||||
* @param string $text - text to preceeding the number of results
|
||||
*
|
||||
**/
|
||||
function result($text)
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['recordCount']) )
|
||||
{
|
||||
if($this->_pageDetails['recordCount'] > $this->_pageDetails['limit'])
|
||||
{
|
||||
$start_row = $this->_pageDetails['page'] > 1 ? (($this->_pageDetails['page']-1)*$this->_pageDetails['limit'])+1:'1';
|
||||
$end_row = ($this->_pageDetails['recordCount'] < ($start_row + $this->_pageDetails['limit']-1)) ? $this->_pageDetails['recordCount'] : ($start_row + $this->_pageDetails['limit']-1);
|
||||
$t = $text.$start_row.'-'.$end_row.' of '.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $text.$this->_pageDetails['recordCount'];
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a list of page numbers separated by $separator
|
||||
*
|
||||
* @param string $separator - defaults to null
|
||||
*
|
||||
**/
|
||||
function pageNumbers($separator=null)
|
||||
{
|
||||
if (empty($this->_pageDetails) || $this->_pageDetails['pageCount'] == 1) { return false; }
|
||||
$t = array();
|
||||
$text = '';
|
||||
$pc = 1;
|
||||
do
|
||||
{
|
||||
if($pc == $this->_pageDetails['page'])
|
||||
{
|
||||
$text = '<em>'.$pc.'</em>';
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$text = $this->Ajax->linkToRemote($pc, array("fallback"=>$this->action."#","url" =>$this->link.$pc,"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$text = $this->Html->link($pc,$this->link.$pc);
|
||||
}
|
||||
}
|
||||
|
||||
$t[] = $text;
|
||||
$pc++;
|
||||
}
|
||||
while ($pc<=$this->_pageDetails['pageCount']);
|
||||
|
||||
$t = implode($separator, $t);
|
||||
|
||||
return $t;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the previous page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text display: defaults to next
|
||||
*
|
||||
**/
|
||||
function prevPage($text='prev')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if ( !empty($this->_pageDetails['previousPage']) )
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['previousPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['previousPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Displays a link to the next page, where the page doesn't exist then
|
||||
* display the $text
|
||||
*
|
||||
* @param string $text - text to display: defaults to next
|
||||
*
|
||||
**/
|
||||
function nextPage($text='next')
|
||||
{
|
||||
if (empty($this->_pageDetails)) { return false; }
|
||||
if (!empty($this->_pageDetails['nextPage']))
|
||||
{
|
||||
if($this->style == 'ajax')
|
||||
{
|
||||
$t = $this->Ajax->linkToRemote($text, array("fallback"=>$this->action."#","url" => $this->link.$this->_pageDetails['nextPage'],"update" => "ajax_update","method"=>"get"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$t = $this->Html->link($text,$this->link.$this->_pageDetails['nextPage']);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php echo $this->renderElement( 'header' ); ?>
|
||||
<?php echo $this->renderElement( 'nav' ); ?>
|
||||
<div id="t_content_container">
|
||||
<div id="t_content">
|
||||
<?php echo $content_for_layout;?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo $this->renderElement( 'footer'); ?>
|
||||
@@ -1,51 +0,0 @@
|
||||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/comments/','get'); ?>
|
||||
<span>
|
||||
<label for="start_date">Start Date:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End Date:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['applications']['name'].' '.$select['applications']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($commentsData)) : ?>
|
||||
|
||||
<table class="comments" summary="User submitted comments.">
|
||||
<tr><th>Date Recorded</th><th>Comment</th></tr>
|
||||
<?php foreach ($commentsData as $var => $val) : ?>
|
||||
<tr><td><?php echo $time->niceShort($val['Result']['created']); ?></td><td><?php echo nl2br(htmlspecialchars($val['Result']['comments'])); ?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if($pagination->setPaging($paging)):?>
|
||||
<ul id="page-numbers">
|
||||
<li><?php echo $pagination->show('Show ', ' '); ?></li>
|
||||
<li><?php echo $pagination->result('Results: '); ?></li>
|
||||
<li><?php echo $pagination->pageNumbers(' '); ?></li>
|
||||
</ul>
|
||||
<?php endif;?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,91 +0,0 @@
|
||||
<h1><?php echo Inflector::humanize($this->name); ?></h1>
|
||||
|
||||
<div id="queryform">
|
||||
<?php echo $html->formTag('/results/','get'); ?>
|
||||
<span>
|
||||
<label for="start_date">Start Date:</label>
|
||||
<input type="text" name="start_date" id="start_date" value="<? echo isset($url_params['start_date']) ? $url_params['start_date'] : ''; ?>" />
|
||||
<label for="end_date">End Date:</label>
|
||||
<input type="text" name="end_date" id="end_date" value="<? echo isset($url_params['end_date']) ? $url_params['end_date'] : ''; ?>" />
|
||||
</span>
|
||||
|
||||
<label for="product">Product:</label>
|
||||
<select name="product" id="product">
|
||||
<?php
|
||||
foreach ($products as $select) :
|
||||
$product = $select['applications']['name'].' '.$select['applications']['version'];
|
||||
$selected = ($product == trim($url_params['product'])) ? ' selected="selected" ' : '';
|
||||
?>
|
||||
<option<?=$selected?>><?=$product?></option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<input type="submit" name="submit" id="submit" value="Go" />
|
||||
</form>
|
||||
<br />
|
||||
<span><small>Date format is yyyy-mm-dd. A blank date will use the largest possible range.</small></span>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($descriptionAndTotalsData)) : ?>
|
||||
<?php
|
||||
/* Prepare data for graphing */
|
||||
$_dataset = '';
|
||||
$_count = 0;
|
||||
$_total = 0;
|
||||
/* We've got to do 2 loops here because I need the totals to calculate
|
||||
* percentages.
|
||||
*/
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
$_total += $val[0]['total'];
|
||||
}
|
||||
foreach ($descriptionAndTotalsData as $var => $val) {
|
||||
// We're putting this in a js string, so escape the double quotes
|
||||
$_description = str_replace('"','\"',$val['issues']['description']);
|
||||
$_percentage = intval(($val[0]['total'] / $_total)*100);
|
||||
|
||||
$_dataset .= "[{$_count}, {$val[0]['total']}, \"{$_description} (n={$val[0]['total']}, {$_percentage}%)\"], ";
|
||||
$_count++;
|
||||
}
|
||||
$_dataset = "[{$_dataset}]";
|
||||
?>
|
||||
<div id="graphcontainer">
|
||||
<canvas id="graph" height="400" width="800">
|
||||
<table class="results" summary="Firefox Uninstallation results.">
|
||||
<tr><th>Reason for uninstalling</th><th>Total</th></tr>
|
||||
<?php foreach ($descriptionAndTotalsData as $var => $val) : ?>
|
||||
<tr><td><?=$val['issues']['description']?></td><td><?=$val[0]['total']?></td></tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</canvas>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var layout = new PlotKit.Layout("bar", {"barOrientation":"horizontal"});
|
||||
layout.addDataset("results", <?=$_dataset?>);
|
||||
layout.evaluate();
|
||||
|
||||
var canvas = MochiKit.DOM.getElement("graph");
|
||||
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout,
|
||||
{
|
||||
"drawYAxis" : false,
|
||||
"drawXAxis" : false,
|
||||
"backgroundColor" : Color.fromHexString('#78c'),
|
||||
"strokeColor" : Color.fromHexString('#777'),
|
||||
"strokeWidth" : 1.0,
|
||||
"enableEvents" : false
|
||||
});
|
||||
|
||||
plotter.render();
|
||||
</script>
|
||||
|
||||
|
||||
<div id="exportbox">
|
||||
<a href="<?php echo $export->buildUrlString('results/comments/',$url_params); ?>">View Any Associated Comments»</a><br />
|
||||
<a href="<?php echo $export->buildUrlString('results/csv/',$url_params); ?>">Download this Data»</a>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div id="notice">There is no data available for your parameters. Please review your search criteria.</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,6 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
|
||||
</IfModule>
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: css.php,v 1.1.1.1 2006-05-24 19:14:24 uid815 Exp $ */
|
||||
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.app.webroot
|
||||
* @since CakePHP v 0.2.9
|
||||
* @version $Revision: 1.1.1.1 $
|
||||
* @modifiedby $LastChangedBy: phpnut $
|
||||
* @lastmodified $Date: 2006-05-24 19:14:24 $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*/
|
||||
require(CONFIGS.'paths.php');
|
||||
require(CAKE.'basics.php');
|
||||
require(LIBS.'folder.php');
|
||||
require(LIBS.'file.php');
|
||||
require(LIBS.'legacy.php');
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $path
|
||||
* @param unknown_type $name
|
||||
* @return unknown
|
||||
*/
|
||||
function make_clean_css ($path, $name)
|
||||
{
|
||||
require(VENDORS.'csspp'.DS.'csspp.php');
|
||||
|
||||
$data = file_get_contents($path);
|
||||
$csspp = new csspp();
|
||||
$output = $csspp->compress($data);
|
||||
|
||||
$ratio = 100-(round(strlen($output)/strlen($data), 3)*100);
|
||||
$output = " /* file: $name, ratio: $ratio% */ " . $output;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $path
|
||||
* @param unknown_type $content
|
||||
* @return unknown
|
||||
*/
|
||||
function write_css_cache ($path, $content)
|
||||
{
|
||||
if (!is_dir(dirname($path)))
|
||||
mkdir(dirname($path));
|
||||
|
||||
$cache = new File($path);
|
||||
return $cache->write($content);
|
||||
}
|
||||
|
||||
if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs))
|
||||
die('Wrong file name.');
|
||||
|
||||
$filename = 'css/'.$regs[1];
|
||||
$filepath = CSS.$regs[1];
|
||||
$cachepath = CACHE.'css'.DS.str_replace(array('/','\\'), '-', $regs[1]);
|
||||
|
||||
if (!file_exists($filepath))
|
||||
die('Wrong file name.');
|
||||
|
||||
|
||||
if (file_exists($cachepath))
|
||||
{
|
||||
$templateModified = filemtime($filepath);
|
||||
$cacheModified = filemtime($cachepath);
|
||||
|
||||
if ($templateModified > $cacheModified)
|
||||
{
|
||||
$output = make_clean_css ($filepath, $filename);
|
||||
write_css_cache ($cachepath, $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = file_get_contents($cachepath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = make_clean_css ($filepath, $filename);
|
||||
write_css_cache ($cachepath, $output);
|
||||
}
|
||||
|
||||
header("Date: ".date("D, j M Y G:i:s ", $templateModified).'GMT');
|
||||
header("Content-Type: text/css");
|
||||
header("Expires: ".gmdate("D, j M Y H:i:s", time()+DAY)." GMT");
|
||||
header("Cache-Control: cache");// HTTP/1.1
|
||||
header("Pragma: cache");// HTTP/1.0
|
||||
print $output;
|
||||
|
||||
?>
|
||||
@@ -1,195 +0,0 @@
|
||||
/* CSS Document */
|
||||
@import url("cake.forms.css");
|
||||
|
||||
* {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
body {
|
||||
font: 76% Verdana, Arial, Sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
img {
|
||||
border:0;
|
||||
}
|
||||
#wrapper {
|
||||
text-align:left;
|
||||
}
|
||||
#header {
|
||||
height: 101px;
|
||||
background: #0D5087 url(../img/cake.header_bg.png) repeat-x left top;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
#content {
|
||||
min-height:400px;
|
||||
background-color: #fff;
|
||||
padding:2em 4em;
|
||||
}
|
||||
#footer {
|
||||
text-align:center;
|
||||
padding:1em 0;
|
||||
font-size:smaller;
|
||||
border-top:1px solid #333;
|
||||
background-color: #063260;
|
||||
color:#fff;
|
||||
line-height:1.5;
|
||||
}
|
||||
#footer a {
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
padding-bottom:0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-family:"Trebuchet MS",Verdana,Arial,Sans-serif;
|
||||
}
|
||||
h1, a {
|
||||
color:#DB8101;
|
||||
}
|
||||
h1 em, a em {
|
||||
color:#008BCC;
|
||||
font-style: normal;
|
||||
}
|
||||
ul.colored a em
|
||||
h2 {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color:#666;
|
||||
}
|
||||
a:hover, a:hover em {
|
||||
color:#A22424;
|
||||
text-decoration:none;
|
||||
}
|
||||
#content p, #content ul, #content ol {
|
||||
line-height:1.5;
|
||||
padding-bottom:1em;
|
||||
}
|
||||
ul, ol {
|
||||
margin-left:3em;
|
||||
}
|
||||
|
||||
/* tables */
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #333;
|
||||
clear:both;
|
||||
margin: 0 0 2em 0;
|
||||
white-space: normal;
|
||||
}
|
||||
th {
|
||||
background-color: #ccc;
|
||||
border-top: 1px solid #fff;
|
||||
border-right: 1px solid #666;
|
||||
border-bottom: 1px solid #666;
|
||||
text-align: center;
|
||||
padding:3px;
|
||||
}
|
||||
table tr td {
|
||||
border-right: 1px solid #ccc;
|
||||
padding:4px 4px;
|
||||
vertical-align:top;
|
||||
text-align: center;
|
||||
}
|
||||
table tr.altRow td {
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
/* scaffold show */
|
||||
|
||||
|
||||
div.related {
|
||||
clear:both;
|
||||
display:block;
|
||||
}
|
||||
dl {
|
||||
line-height:2em;
|
||||
margin:1em;
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
vertical-align:top;
|
||||
}
|
||||
dd {
|
||||
margin-left:10em;
|
||||
margin-top:-2em;
|
||||
vertical-align:top;
|
||||
}
|
||||
|
||||
/* scaffold buttons */
|
||||
|
||||
|
||||
.notice {
|
||||
color: #DB8101;
|
||||
background-color: #ddd;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
}
|
||||
.tip {
|
||||
color: #DB8101;
|
||||
background-color: #ddd;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
ul.actions {
|
||||
list-style: none;
|
||||
text-align:left;
|
||||
margin:2em 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul.actions li {
|
||||
margin-left:1em;
|
||||
list-style: none;
|
||||
display: inline;
|
||||
}
|
||||
ul.actions li a, ul.actions li input {
|
||||
padding: 2px 12px;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
line-height: 24px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
}
|
||||
ul.actions li a:hover {
|
||||
color: #DB8101;
|
||||
background-color:#fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
td.listactions {
|
||||
width: 14em;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td.listactions a {
|
||||
padding: 0px 8px;
|
||||
text-align:center;
|
||||
font-weight: bold;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td.listactions a:hover {
|
||||
color: #fff;
|
||||
background-color:#DB8101;
|
||||
}
|
||||
|
||||
/* index links */
|
||||
|
||||
ul.colored a {
|
||||
|
||||
}
|
||||
ul.colored a em {
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/* form.css */
|
||||
|
||||
form {
|
||||
margin: 0 4px;
|
||||
font-size: 120%;
|
||||
border-width: 0px 0px 0px 0px;
|
||||
border-style: solid;
|
||||
border-color: #DB8101;
|
||||
}
|
||||
|
||||
form fieldset {
|
||||
font-size: 100%;
|
||||
border-color: #000000;
|
||||
border-width: 1px 0px 0px 0px;
|
||||
border-style: solid none none none;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
form fieldset legend {
|
||||
font-size: 150%;
|
||||
font-weight: normal;
|
||||
color: #000;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
label u {
|
||||
font-style: normal;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
input, select, textarea {
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
form div {
|
||||
clear: left;
|
||||
display: block;
|
||||
margin: 5px 0px 0px 0px;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
form fieldset div.notes {
|
||||
float: right;
|
||||
width: 158px;
|
||||
height: auto;
|
||||
margin: 0px 0px 10px 10px;
|
||||
padding: 5px;
|
||||
border: 1px solid #666;
|
||||
background-color: #ffffe1;
|
||||
color: #666;
|
||||
font-size: 88%;
|
||||
}
|
||||
|
||||
form fieldset div.notes h4 {
|
||||
background-image: url(/images/icon_info.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: top left;
|
||||
padding: 3px 0px 3px 27px;
|
||||
border-width: 0px 0px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: #666;
|
||||
color: #666;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
form fieldset div.notes p {
|
||||
margin: 0em 0em 1.2em 0em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
form fieldset div.notes p.last {
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
form div fieldset {
|
||||
clear: none;
|
||||
border-width: 0px 1px 0px 1px;
|
||||
border-style: solid;
|
||||
border-color: #666;
|
||||
margin: 0px 0px 0px 142px;
|
||||
padding: 0px 5px 5px 5px;
|
||||
}
|
||||
|
||||
form div fieldset legend {
|
||||
font-size: 100%;
|
||||
padding: 0px 3px 0px 9px;
|
||||
}
|
||||
|
||||
form div.required fieldset legend {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form div label {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 200px;
|
||||
background-color: #f4f4f4;
|
||||
font-size: 16px;
|
||||
padding: 3px 5px;
|
||||
margin: 0px 0px 5px 0px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
form div.optional label, label.optional {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form div.required label, label.required {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form div label.labelCheckbox, form div label.labelRadio {
|
||||
float: none;
|
||||
display: block;
|
||||
margin: 0px 0px 5px 142px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
form div fieldset label.labelCheckbox, form div fieldset label.labelRadio {
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
p.error {
|
||||
color: #DB8101;
|
||||
background-color: #DBA941;
|
||||
font-size: 14px;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
form div input, form div select, form div textarea {
|
||||
padding: 1px 3px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
form div input.inputFile {
|
||||
width: 211px;
|
||||
}
|
||||
|
||||
form div select.selectOne, form div select.selectMultiple {
|
||||
width: 211px;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
form div input.inputCheckbox, form div input.inputRadio, input.inputCheckbox, input.inputRadio {
|
||||
display: inline;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background-color: transparent;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
form div.submit {
|
||||
padding: 0px 0px 0px 140px;
|
||||
clear:both;
|
||||
display:block;
|
||||
}
|
||||
|
||||
div.submit input {
|
||||
padding: 2px 12px;
|
||||
color: #DB8101;
|
||||
background-color:#ccc;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
}
|
||||
div.submit input:hover {
|
||||
padding: 2px 12px;
|
||||
color: #fff;
|
||||
background-color:#DB8101;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
text-decoration: none;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
form div.submit div input.inputSubmit, form div.submit div input.inputButton {
|
||||
float: right;
|
||||
margin: 0px 0px 0px 5px;
|
||||
}
|
||||
|
||||
form div small {
|
||||
display: block;
|
||||
margin: 0px 0px 5px 142px;
|
||||
padding: 1px 3px;
|
||||
font-size: 88%;
|
||||
}
|
||||
|
||||
/* form.import.css */
|
||||
|
||||
form fieldset legend {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
form input, form select, form textarea {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
div.optional label:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
div.required label:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
|
||||
display: block;
|
||||
width: 190px;
|
||||
padding: 4px 0px 0px 18px;
|
||||
text-indent: -18px;
|
||||
line-height: 120%;
|
||||
}
|
||||
|
||||
form div label.labelCheckbox input.inputCheckbox, form div label.labelRadio input.inputRadio, label.labelCheckbox input.inputCheckbox, label.labelRadio input.inputRadio {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
|
||||
width: 160px;
|
||||
margin: 0px 0px 0px 18px;
|
||||
}
|
||||
|
||||
form div label.compact {
|
||||
display: inline;
|
||||
width: auto;
|
||||
padding: 4px 10px 0px 0px;
|
||||
text-indent: 0px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div.wide label {
|
||||
float: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
form div label.wide {
|
||||
width: 348px;
|
||||
}
|
||||
|
||||
form div.wide input.inputText, form div.wide input.inputPassword, form div.wide input.inputFile, form div.wide select, form div.wide textarea {
|
||||
width: 344px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form div.notes p, form div small {
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
form div.wide small {
|
||||
margin: 0px 0px 5px 0px;
|
||||
}
|
||||
|
||||
div.date select {
|
||||
width:auto;
|
||||
}
|
||||
|
||||
select.autoWidth {
|
||||
width:auto;
|
||||
}
|
||||
|
||||
option {
|
||||
padding-left:1em;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
form div,
|
||||
form div label.labelCheckbox, form div label.labelRadio,
|
||||
form div small,
|
||||
form div label.labelCheckbox, form div label.labelRadio, label.labelCheckbox, label.labelRadio {
|
||||
height: expression('1%');
|
||||
}
|
||||
form div fieldset input.inputText, form div fieldset input.inputPassword, form div fieldset input.inputFile, form div fieldset textarea.inputTextarea {
|
||||
margin: expression('0px 0px 0px -124px');
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/* Screen Stylesheet */
|
||||
|
||||
/* This is temporary while we use the scaffolding */
|
||||
@import url("cake.default.css");
|
||||
table { clear:none; }
|
||||
|
||||
/* CORE STYLES */
|
||||
|
||||
body{
|
||||
background-color:#788;
|
||||
}
|
||||
div#t_title{
|
||||
background-color:#ddd;
|
||||
height:50px;
|
||||
padding-left:8px;
|
||||
}
|
||||
div#t_title h1{
|
||||
font-size:1.7em;
|
||||
padding-top:10px;
|
||||
color:#677;
|
||||
}
|
||||
div#t_content_container{
|
||||
}
|
||||
div#t_content{
|
||||
padding: 20px 10px 100px 10px;
|
||||
margin-left:151px;
|
||||
background-image:url('../img/bg.jpg');
|
||||
background-position:bottom right;
|
||||
background-repeat:no-repeat;
|
||||
min-height:200px;
|
||||
}
|
||||
div#t_wrapper{
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
div#t_border{
|
||||
border-left:1px solid #111;
|
||||
border-right:1px solid #111;
|
||||
border-bottom:1px solid #111;
|
||||
margin:0px 30px 0px 30px;
|
||||
}
|
||||
|
||||
div#t_nav {
|
||||
padding:20px 0px 50px 0px;
|
||||
float:left;
|
||||
width:151px;
|
||||
}
|
||||
div#t_nav ul {
|
||||
list-style-type:none;
|
||||
padding:2px 0px 0px 0px;
|
||||
margin:0px;
|
||||
}
|
||||
div#t_nav ul li{
|
||||
padding:2px 0px 2px 0px;
|
||||
}
|
||||
div#t_nav ul li a{
|
||||
text-decoration:none;
|
||||
font-size:.8em;
|
||||
padding:6px 0px 6px 8px;
|
||||
margin:0px 0px 0px 0px;
|
||||
color:#566;
|
||||
border:none;
|
||||
}
|
||||
div#t_nav ul li a:hover{
|
||||
color:#f80;
|
||||
}
|
||||
div#t_nav h3 {
|
||||
padding:5px 0px 0px 5px;
|
||||
font-size:.9em;
|
||||
}
|
||||
div#t_footer {
|
||||
clear:both;
|
||||
border-top:1px solid #111;
|
||||
}
|
||||
|
||||
div#t_content h1 {
|
||||
margin-bottom:100px;
|
||||
font-size:1.6em;
|
||||
}
|
||||
|
||||
a.skipnav {
|
||||
position:absolute;
|
||||
visibility:hidden;
|
||||
}
|
||||
|
||||
div#queryform {
|
||||
margin: 5px 20px 5px 20px;
|
||||
padding-bottom:20px;
|
||||
width:700px;
|
||||
}
|
||||
div#queryform label {
|
||||
font-size:.8em;
|
||||
font-weight:bold;
|
||||
}
|
||||
div#queryform input[type="text"]{
|
||||
width:7em;
|
||||
}
|
||||
|
||||
div#exportbox {
|
||||
}
|
||||
|
||||
/* Classes for graph/table data. (Generally just padding) */
|
||||
.results {
|
||||
padding: 5px 5px 5px 5px;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
div#notice {
|
||||
background-color:#ecc;
|
||||
border:1px dashed #daa;
|
||||
text-align:center;
|
||||
padding:6px 6px 6px 6px;
|
||||
margin:6px 20px 6px 20px;
|
||||
}
|
||||
|
||||
table.comments tr {
|
||||
}
|
||||
|
||||
table.comments tr td{
|
||||
text-align:left;
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
div.bar_chart_label {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
font-size: small;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.2 KiB |
@@ -1 +0,0 @@
|
||||
deny from all
|
||||
@@ -1,244 +0,0 @@
|
||||
2006-04-29 v1.3.1 (bug fix release)
|
||||
|
||||
- Fix sendXMLHttpRequest sendContent regression
|
||||
- Internet Explorer fix in MochiKit.Logging (printfire exception)
|
||||
- Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async
|
||||
|
||||
2006-04-26 v1.3 "warp zone"
|
||||
|
||||
- IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
|
||||
- IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
|
||||
- New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method
|
||||
- New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array
|
||||
- Refactored MochiRegExp example to use MochiKit.Signal
|
||||
- New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.
|
||||
- MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").
|
||||
- MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.
|
||||
- Native Console Logging for the default MochiKit.Logging logger
|
||||
- New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
|
||||
- New MochiKit.Signal example: draggable
|
||||
- Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly
|
||||
- Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
|
||||
- Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.
|
||||
- Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size
|
||||
- MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.
|
||||
- MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.
|
||||
- New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
|
||||
- MochiKit.Base.isNull no longer matches undefined
|
||||
- example doctypes changed to HTML4
|
||||
- isDateLike no longer throws error on null
|
||||
- New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
|
||||
- updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth
|
||||
- formContents now works with FORM tags that have a name attribute
|
||||
- Documentation now uses MochiKit to generate a function index
|
||||
|
||||
2006-01-26 v1.2 "the ocho"
|
||||
|
||||
- Fixed MochiKit.Color.Color.lighterColorWithLevel
|
||||
- Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.
|
||||
- Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.
|
||||
- MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].
|
||||
- MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility
|
||||
- MochiKit.Iter.forEach will now catch StopIteration to break
|
||||
- New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document
|
||||
- MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino
|
||||
- MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element
|
||||
currently in the document instead of always creating one.
|
||||
- MochiKit.Base now has operator.mul
|
||||
- MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute
|
||||
- Added new MochiKit.Color constructors fromComputedStyle and fromText
|
||||
- MochiKit.DOM.setNodeAttribute should work now
|
||||
- MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string
|
||||
- MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties
|
||||
- MochiKit.DOM.scrapeText now walks the DOM tree in-order
|
||||
- MochiKit.LoggingPane now sanitizes the window name to work around IE bug
|
||||
- MochiKit.DOM now translates usemap to useMap to work around IE bug
|
||||
- MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
|
||||
- Added new MochiKit.DOM documentation on element visibility
|
||||
- New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG
|
||||
|
||||
2005-11-14 v1.1
|
||||
|
||||
- Fixed a bug in numberFormatter with large numbers
|
||||
- Massively overhauled documentation
|
||||
- Fast-path for primitives in MochiKit.Base.compare
|
||||
- New groupby and groupby_as_array in MochiKit.Iter
|
||||
- Added iterator factory adapter for objects that implement iterateNext()
|
||||
- Fixed isoTimestamp to handle timestamps with time zone correctly
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET
|
||||
- New MochiKit.DOM formContents and enhancement to queryString to support it
|
||||
- Updated view_source example to use dp.SyntaxHighlighter 1.3.0
|
||||
- MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)
|
||||
- MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)
|
||||
- MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)
|
||||
- MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the *last* argument, not the first when this feature
|
||||
is used.
|
||||
- MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string
|
||||
- Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes
|
||||
- escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.
|
||||
- Added DeferredLock to Async
|
||||
- Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM
|
||||
- Moved all color support out of MochiKit.Visual and into MochiKit.Color
|
||||
- Fixed range() to accept a negative step
|
||||
- New alias to MochiKit.swapDOM called removeElement
|
||||
- New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})
|
||||
- New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising
|
||||
- Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)
|
||||
|
||||
2005-10-24 v1.0
|
||||
|
||||
- New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter
|
||||
- New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage
|
||||
- New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool
|
||||
- Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")
|
||||
- Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
|
||||
- Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format
|
||||
- MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
|
||||
- Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond
|
||||
- Fixed infinite recusion bug when using roundClass("DIV", ...)
|
||||
- Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly
|
||||
- Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert
|
||||
- Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null
|
||||
|
||||
2005-10-08 v0.90
|
||||
|
||||
- Fixed ISO compliance with toISODate
|
||||
- Added missing operator.sub
|
||||
- Placated Mozilla's strict warnings a bit
|
||||
- Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.
|
||||
- Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)
|
||||
- Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM
|
||||
- Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.
|
||||
|
||||
2005-08-12 v0.80
|
||||
|
||||
- Source highlighting in all examples, moved to a view-source example
|
||||
- Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
|
||||
- Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).
|
||||
- Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement
|
||||
- Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)
|
||||
- Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
|
||||
- Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
|
||||
- Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id
|
||||
- Added missing THEAD convenience function to MochiKit.DOM
|
||||
- Added lstrip, rstrip, strip to MochiKit.Format
|
||||
- Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM
|
||||
- MochiKit.Iter.iextend now has a fast-path for array-like objects
|
||||
- Added HSV color space support to MochiKit.Visual
|
||||
- Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly
|
||||
- Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope
|
||||
|
||||
2005-08-04 v0.70
|
||||
|
||||
- New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.
|
||||
- sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests
|
||||
- Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
|
||||
- Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.
|
||||
- Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).
|
||||
- Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString
|
||||
- MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).
|
||||
- Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
|
||||
- Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
|
||||
- Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!
|
||||
|
||||
2005-07-29 v0.60
|
||||
|
||||
- Beefed up the MochiKit.DOM test suite
|
||||
- Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before
|
||||
- Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName
|
||||
- Added a "packed" version in packed/MochiKit/MochiKit.js
|
||||
- Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization
|
||||
- MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.
|
||||
- Several minor documentation corrections
|
||||
|
||||
2005-07-27 v0.50
|
||||
|
||||
- Initial Release
|
||||
@@ -1,69 +0,0 @@
|
||||
MochiKit is dual-licensed software. It is available under the terms of the
|
||||
MIT License, or the Academic Free License version 2.1. The full text of
|
||||
each license is included below.
|
||||
|
||||
MIT License
|
||||
===========
|
||||
|
||||
Copyright (c) 2005 Bob Ippolito. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
Academic Free License v. 2.1
|
||||
============================
|
||||
|
||||
Copyright (c) 2005 Bob Ippolito. All rights reserved.
|
||||
|
||||
This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
|
||||
|
||||
Licensed under the Academic Free License version 2.1
|
||||
|
||||
1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following:
|
||||
|
||||
a) to reproduce the Original Work in copies;
|
||||
|
||||
b) to prepare derivative works ("Derivative Works") based upon the Original Work;
|
||||
|
||||
c) to distribute copies of the Original Work and Derivative Works to the public;
|
||||
|
||||
d) to perform the Original Work publicly; and
|
||||
|
||||
e) to display the Original Work publicly.
|
||||
|
||||
2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works.
|
||||
|
||||
3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work.
|
||||
|
||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license.
|
||||
|
||||
5) This section intentionally omitted.
|
||||
|
||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
|
||||
|
||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer.
|
||||
|
||||
8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions.
|
||||
|
||||
10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
|
||||
|
||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License.
|
||||
|
||||
12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
|
||||
|
||||
13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
|
||||
|
||||
14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
|
||||
|
||||
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.
|
||||
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
Changes
|
||||
META.json
|
||||
MANIFEST This list of files
|
||||
LICENSE.txt
|
||||
doc/html/MochiKit/Async.html
|
||||
doc/html/MochiKit/Base.html
|
||||
doc/html/MochiKit/Color.html
|
||||
doc/html/MochiKit/DateTime.html
|
||||
doc/html/MochiKit/DOM.html
|
||||
doc/html/MochiKit/Format.html
|
||||
doc/html/MochiKit/index.html
|
||||
doc/html/MochiKit/Iter.html
|
||||
doc/html/MochiKit/Logging.html
|
||||
doc/html/MochiKit/LoggingPane.html
|
||||
doc/html/MochiKit/Signal.html
|
||||
doc/html/MochiKit/VersionHistory.html
|
||||
doc/html/MochiKit/Visual.html
|
||||
doc/js/toc.js
|
||||
doc/rst/MochiKit/Async.rst
|
||||
doc/rst/MochiKit/Base.rst
|
||||
doc/rst/MochiKit/Color.rst
|
||||
doc/rst/MochiKit/DateTime.rst
|
||||
doc/rst/MochiKit/DOM.rst
|
||||
doc/rst/MochiKit/Format.rst
|
||||
doc/rst/MochiKit/index.rst
|
||||
doc/rst/MochiKit/Iter.rst
|
||||
doc/rst/MochiKit/Logging.rst
|
||||
doc/rst/MochiKit/LoggingPane.rst
|
||||
doc/rst/MochiKit/Signal.rst
|
||||
doc/rst/MochiKit/VersionHistory.rst
|
||||
doc/rst/MochiKit/Visual.rst
|
||||
examples/ajax_tables/ajax_tables.css
|
||||
examples/ajax_tables/ajax_tables.js
|
||||
examples/ajax_tables/domains.json
|
||||
examples/ajax_tables/domains.xml
|
||||
examples/ajax_tables/index.html
|
||||
examples/color_wheel/color_wheel.css
|
||||
examples/color_wheel/color_wheel.js
|
||||
examples/color_wheel/index.html
|
||||
examples/draggable/draggable.css
|
||||
examples/draggable/draggable.js
|
||||
examples/draggable/index.html
|
||||
examples/interpreter/index.html
|
||||
examples/interpreter/interpreter.css
|
||||
examples/interpreter/interpreter.js
|
||||
examples/key_events/index.html
|
||||
examples/key_events/key_events.css
|
||||
examples/key_events/key_events.js
|
||||
examples/logging_pane/index.html
|
||||
examples/logging_pane/logging_pane.css
|
||||
examples/logging_pane/logging_pane.js
|
||||
examples/mochiregexp/index.html
|
||||
examples/mochiregexp/mochiregexp.css
|
||||
examples/mochiregexp/mochiregexp.js
|
||||
examples/rounded_corners/index.html
|
||||
examples/rounded_corners/rounded_corners.css
|
||||
examples/rounded_corners/rounded_corners.js
|
||||
examples/sortable_tables/index.html
|
||||
examples/sortable_tables/sortable_tables.css
|
||||
examples/sortable_tables/sortable_tables.js
|
||||
examples/view-source/view-source.css
|
||||
examples/view-source/view-source.html
|
||||
examples/view-source/view-source.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushPython.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushSql.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushVb.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shBrushXml.js
|
||||
examples/view-source/lib/SyntaxHighlighter/shCore.js
|
||||
examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css
|
||||
examples/view-source/lib/SyntaxHighlighter/Tests.html
|
||||
include/css/documentation.css
|
||||
include/css/general.css
|
||||
MochiKit/__package__.js
|
||||
MochiKit/Async.js
|
||||
MochiKit/Base.js
|
||||
MochiKit/Color.js
|
||||
MochiKit/DateTime.js
|
||||
MochiKit/DOM.js
|
||||
MochiKit/Format.js
|
||||
MochiKit/Iter.js
|
||||
MochiKit/Logging.js
|
||||
MochiKit/LoggingPane.js
|
||||
MochiKit/MochiKit.js
|
||||
MochiKit/MockDOM.js
|
||||
MochiKit/Signal.js
|
||||
MochiKit/Test.js
|
||||
MochiKit/Visual.js
|
||||
packed/MochiKit/__package__.js
|
||||
packed/MochiKit/MochiKit.js
|
||||
tests/index.html
|
||||
tests/test_Base.js
|
||||
tests/test_Color.js
|
||||
tests/test_DateTime.js
|
||||
tests/test_Format.js
|
||||
tests/test_Iter.js
|
||||
tests/test_Logging.js
|
||||
tests/test_MochiKit-Async.html
|
||||
tests/test_MochiKit-Base.html
|
||||
tests/test_MochiKit-Color.html
|
||||
tests/test_MochiKit-DateTime.html
|
||||
tests/test_MochiKit-DOM.html
|
||||
tests/test_MochiKit-Format.html
|
||||
tests/test_MochiKit-Iter.html
|
||||
tests/test_MochiKit-JSAN.html
|
||||
tests/test_MochiKit-Logging.html
|
||||
tests/test_MochiKit-MochiKit.html
|
||||
tests/test_MochiKit-Signal.html
|
||||
tests/test_Signal.js
|
||||
tests/SimpleTest/SimpleTest.js
|
||||
tests/SimpleTest/test.css
|
||||
tests/SimpleTest/TestRunner.js
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"recommends": {
|
||||
"JSAN": "0.10"
|
||||
},
|
||||
"name": "MochiKit",
|
||||
"license": "mit",
|
||||
"author": [
|
||||
"Bob Ippolito <bob@redivi.com>"
|
||||
],
|
||||
"abstract": "Python-inspired JavaScript kit",
|
||||
"generated_by": "MochiKit's build script",
|
||||
"build_requires": {
|
||||
"Test.Simple": "0.11"
|
||||
},
|
||||
"version": "1.3.1",
|
||||
"provides": {}
|
||||
}
|
||||
@@ -1,606 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Async - manage asynchronous tasks</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Async - manage asynchronous tasks</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
var url = "/src/b/bo/bob/MochiKit.Async/META.json";
|
||||
/*
|
||||
|
||||
META.json looks something like this:
|
||||
|
||||
{"name": "MochiKit", "version": "0.5"}
|
||||
|
||||
*/
|
||||
var d = loadJSONDoc(url);
|
||||
var gotMetadata = function (meta) {
|
||||
if (MochiKit.Async.VERSION == meta.version) {
|
||||
alert("You have the newest MochiKit.Async!");
|
||||
} else {
|
||||
alert("MochiKit.Async "
|
||||
+ meta.version
|
||||
+ " is available, upgrade!");
|
||||
}
|
||||
};
|
||||
var metadataFetchFailed = function (err) {
|
||||
alert("The metadata for MochiKit.Async could not be fetched :(");
|
||||
};
|
||||
d.addCallbacks(gotMetadata, metadataFetchFailed);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Async provides facilities to manage asynchronous
|
||||
(as in AJAX <a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a>) tasks. The model for asynchronous computation
|
||||
used in this module is heavily inspired by Twisted <a class="footnote-reference" href="#id8" id="id2" name="id2">[2]</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="deferred" name="deferred">Deferred</a></h2>
|
||||
<p>The Deferred constructor encapsulates a single value that
|
||||
is not available yet. The most important example of this
|
||||
in the context of a web browser would be an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
to a server. The importance of the Deferred is that it
|
||||
allows a consistent API to be exposed for all asynchronous
|
||||
computations that occur exactly once.</p>
|
||||
<p>The producer of the Deferred is responsible for doing all
|
||||
of the complicated work behind the scenes. This often
|
||||
means waiting for a timer to fire, or waiting for an event
|
||||
(e.g. <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> of <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>).
|
||||
It could also be coordinating several events (e.g.
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> with a timeout, or several Deferreds
|
||||
(e.g. fetching a set of XML documents that should be
|
||||
processed at the same time).</p>
|
||||
<p>Since these sorts of tasks do not respond immediately, the
|
||||
producer of the Deferred does the following steps before
|
||||
returning to the consumer:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Create a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred();</a> object and keep a reference
|
||||
to it, because it will be needed later when the value is
|
||||
ready.</li>
|
||||
<li>Setup the conditions to create the value requested (e.g.
|
||||
create a new <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>, set its
|
||||
<tt class="docutils literal"><span class="pre">onreadystatechange</span></tt>).</li>
|
||||
<li>Return the <a class="mochiref reference" href="#fn-deferred">Deferred</a> object.</li>
|
||||
</ol>
|
||||
<p>Since the value is not yet ready, the consumer attaches
|
||||
a function to the Deferred that will be called when the
|
||||
value is ready. This is not unlike <tt class="docutils literal"><span class="pre">setTimeout</span></tt>, or
|
||||
other similar facilities you may already be familiar with.
|
||||
The consumer can also attach an "errback" to the
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a>, which is a callback for error handling.</p>
|
||||
<p>When the value is ready, the producer simply calls
|
||||
<tt class="docutils literal"><span class="pre">myDeferred.callback(theValue)</span></tt>. If an error occurred,
|
||||
it should call <tt class="docutils literal"><span class="pre">myDeferred.errback(theValue)</span></tt> instead.
|
||||
As soon as this happens, the callback that the consumer
|
||||
attached to the <a class="mochiref reference" href="#fn-deferred">Deferred</a> is called with <tt class="docutils literal"><span class="pre">theValue</span></tt>
|
||||
as the only argument.</p>
|
||||
<p>There are quite a few additional "advanced" features
|
||||
baked into <a class="mochiref reference" href="#fn-deferred">Deferred</a>, such as cancellation and
|
||||
callback chains, so take a look at the API
|
||||
reference if you would like to know more!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="errors" name="errors">Errors</a></h2>
|
||||
<p>
|
||||
<a name="fn-alreadycallederror"></a>
|
||||
<a class="mochidef reference" href="#fn-alreadycallederror">AlreadyCalledError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> if <tt class="docutils literal"><span class="pre">.callback</span></tt> or
|
||||
<tt class="docutils literal"><span class="pre">.errback</span></tt> are called more than once.</blockquote>
|
||||
<p>
|
||||
<a name="fn-browsercomplianceerror"></a>
|
||||
<a class="mochidef reference" href="#fn-browsercomplianceerror">BrowserComplianceError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown when the JavaScript runtime is not capable of performing
|
||||
the given function. Currently, this happens if the browser
|
||||
does not support <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-cancellederror"></a>
|
||||
<a class="mochidef reference" href="#fn-cancellederror">CancelledError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown by a <a class="mochiref reference" href="#fn-deferred">Deferred</a> when it is cancelled,
|
||||
unless a canceller is present and throws something else.</blockquote>
|
||||
<p>
|
||||
<a name="fn-genericerror"></a>
|
||||
<a class="mochidef reference" href="#fn-genericerror">GenericError</a>:</p>
|
||||
<blockquote>
|
||||
Results passed to <tt class="docutils literal"><span class="pre">.fail</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> of a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
|
||||
are wrapped by this <tt class="docutils literal"><span class="pre">Error</span></tt> if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-xmlhttprequesterror"></a>
|
||||
<a class="mochidef reference" href="#fn-xmlhttprequesterror">XMLHttpRequestError</a>:</p>
|
||||
<blockquote>
|
||||
Thrown when an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> does not complete successfully
|
||||
for any reason. The <tt class="docutils literal"><span class="pre">req</span></tt> property of the error is the failed
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object, and for convenience the <tt class="docutils literal"><span class="pre">number</span></tt>
|
||||
property corresponds to <tt class="docutils literal"><span class="pre">req.status</span></tt>.</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-deferred"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred">Deferred()</a>:</p>
|
||||
<blockquote>
|
||||
Encapsulates a sequence of callbacks in response to a value that
|
||||
may not yet be available. This is modeled after the Deferred class
|
||||
from Twisted <a class="footnote-reference" href="#id9" id="id3" name="id3">[3]</a>.</blockquote>
|
||||
<blockquote>
|
||||
<p>Why do we want this? JavaScript has no threads, and even if it did,
|
||||
threads are hard. Deferreds are a way of abstracting non-blocking
|
||||
events, such as the final response to an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</p>
|
||||
<p>The sequence of callbacks is internally represented as a list
|
||||
of 2-tuples containing the callback/errback pair. For example,
|
||||
the following call sequence:</p>
|
||||
<pre class="literal-block">
|
||||
var d = new Deferred();
|
||||
d.addCallback(myCallback);
|
||||
d.addErrback(myErrback);
|
||||
d.addBoth(myBoth);
|
||||
d.addCallbacks(myCallback, myErrback);
|
||||
</pre>
|
||||
<p>is translated into a <a class="mochiref reference" href="#fn-deferred">Deferred</a> with the following internal
|
||||
representation:</p>
|
||||
<pre class="literal-block">
|
||||
[
|
||||
[myCallback, null],
|
||||
[null, myErrback],
|
||||
[myBoth, myBoth],
|
||||
[myCallback, myErrback]
|
||||
]
|
||||
</pre>
|
||||
<p>The <a class="mochiref reference" href="#fn-deferred">Deferred</a> also keeps track of its current status (fired).
|
||||
Its status may be one of the following three values:</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="14%" />
|
||||
<col width="86%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">Value</th>
|
||||
<th class="head">Condition</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td>-1</td>
|
||||
<td>no value yet (initial condition)</td>
|
||||
</tr>
|
||||
<tr><td>0</td>
|
||||
<td>success</td>
|
||||
</tr>
|
||||
<tr><td>1</td>
|
||||
<td>error</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>A <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the error state if one of the following
|
||||
conditions are met:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>The result given to callback or errback is "<tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>"</li>
|
||||
<li>The callback or errback threw while executing. If the thrown object
|
||||
is not <tt class="docutils literal"><span class="pre">instanceof</span> <span class="pre">Error</span></tt>, it will be wrapped with
|
||||
<a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</li>
|
||||
</ol>
|
||||
<p>Otherwise, the <a class="mochiref reference" href="#fn-deferred">Deferred</a> will be in the success state. The state
|
||||
of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> determines the next element in the callback
|
||||
sequence to run.</p>
|
||||
<p>When a callback or errback occurs with the example deferred chain, something
|
||||
equivalent to the following will happen (imagine that exceptions are caught
|
||||
and returned as-is):</p>
|
||||
<pre class="literal-block">
|
||||
// d.callback(result) or d.errback(result)
|
||||
if (!(result instanceof Error)) {
|
||||
result = myCallback(result);
|
||||
}
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
}
|
||||
result = myBoth(result);
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
} else {
|
||||
result = myCallback(result);
|
||||
}
|
||||
</pre>
|
||||
<p>The result is then stored away in case another step is added to the
|
||||
callback sequence. Since the <a class="mochiref reference" href="#fn-deferred">Deferred</a> already has a value
|
||||
available, any new callbacks added will be called immediately.</p>
|
||||
<p>There are two other "advanced" details about this implementation that are
|
||||
useful:</p>
|
||||
<p>Callbacks are allowed to return <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances,
|
||||
so you can build complicated sequences of events with (relative) ease.</p>
|
||||
<p>The creator of the <a class="mochiref reference" href="#fn-deferred">Deferred</a> may specify a canceller. The
|
||||
canceller is a function that will be called if
|
||||
<a class="mochiref reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel</a> is called before the
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> fires. You can use this to allow an
|
||||
<tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to be cleanly cancelled, for example. Note that
|
||||
cancel will fire the <a class="mochiref reference" href="#fn-deferred">Deferred</a> with a
|
||||
<a class="mochiref reference" href="#fn-cancellederror">CancelledError</a> (unless your canceller throws or returns
|
||||
a different <tt class="docutils literal"><span class="pre">Error</span></tt>), so errbacks should be prepared to handle that
|
||||
<tt class="docutils literal"><span class="pre">Error</span></tt> gracefully for cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addboth"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addboth">Deferred.prototype.addBoth(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add the same function as both a callback and an errback as the
|
||||
next element on the callback sequence. This is useful for code
|
||||
that you want to guarantee to run, e.g. a finalizer.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback or
|
||||
errback will be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addcallback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addcallback">Deferred.prototype.addCallback(func[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a single callback to the end of the callback sequence.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the callback will
|
||||
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.addcallbacks"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.addcallbacks">Deferred.prototype.addCallbacks(callback, errback)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add separate callback and errback to the end of the callback
|
||||
sequence. Either callback or errback may be <tt class="docutils literal"><span class="pre">null</span></tt>,
|
||||
but not both.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">callback</span></tt> or <tt class="docutils literal"><span class="pre">errback</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
|
||||
then it will be chained (its value or error will be passed to the
|
||||
next callback). Note that once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained,
|
||||
it can no longer accept new callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.adderrback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.adderrback">Deferred.prototype.addErrback(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a single errback to the end of the callback sequence.</p>
|
||||
<p>If additional arguments are given, then <tt class="docutils literal"><span class="pre">func</span></tt> will be replaced
|
||||
with <a class="mochiref reference" href="Base.html#fn-partial">MochiKit.Base.partial.apply(null, arguments)</a>. This
|
||||
differs from <a class="reference" href="http://twistedmatrix.com/">Twisted</a>, because the result of the errback will
|
||||
be the <em>last</em> argument passed to <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">func</span></tt> returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned <tt class="docutils literal"><span class="pre">Deferred</span></tt> is chained, it can no longer accept new
|
||||
callbacks.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.callback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Begin the callback sequence with a non-<tt class="docutils literal"><span class="pre">Error</span></tt> result. Result
|
||||
may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
|
||||
be called exactly once on a <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.cancel"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.cancel">Deferred.prototype.cancel()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Cancels a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has not yet received a value,
|
||||
or is waiting on another <a class="mochiref reference" href="#fn-deferred">Deferred</a> as its value.</p>
|
||||
<p>If a canceller is defined, the canceller is called.
|
||||
If the canceller did not return an <tt class="docutils literal"><span class="pre">Error</span></tt>, or there
|
||||
was no canceller, then the errback chain is started
|
||||
with <a class="mochiref reference" href="#fn-cancellederror">CancelledError</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferred.prototype.errback"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Begin the callback sequence with an error result.
|
||||
Result may be any value except for a <a class="mochiref reference" href="#fn-deferred">Deferred</a>,
|
||||
but if <tt class="docutils literal"><span class="pre">!(result</span> <span class="pre">instanceof</span> <span class="pre">Error)</span></tt>, it will be wrapped
|
||||
with <a class="mochiref reference" href="#fn-genericerror">GenericError</a>.</p>
|
||||
<p>Either <tt class="docutils literal"><span class="pre">.callback</span></tt> or <tt class="docutils literal"><span class="pre">.errback</span></tt> should
|
||||
be called exactly once on a
|
||||
<a name="fn-deferred"></a>
|
||||
<a class="mochidef reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock">DeferredLock()</a>:</p>
|
||||
<blockquote>
|
||||
<p>A lock for asynchronous systems.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">locked</span></tt> property of a <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> will be <tt class="docutils literal"><span class="pre">true</span></tt> if
|
||||
it locked, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. Do not change this property.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock.prototype.acquire"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock.prototype.acquire">DeferredLock.prototype.acquire()</a>:</p>
|
||||
<blockquote>
|
||||
Attempt to acquire the lock. Returns a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that fires on
|
||||
lock acquisition with the <a class="mochiref reference" href="#fn-deferredlock">DeferredLock</a> as the value.
|
||||
If the lock is locked, then the <a class="mochiref reference" href="#fn-deferred">Deferred</a> goes into a waiting
|
||||
list.</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlock.prototype.release"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlock.prototype.release">DeferredLock.prototype.release()</a>:</p>
|
||||
<blockquote>
|
||||
Release the lock. If there is a waiting list, then the first
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> in that waiting list will be called back.</blockquote>
|
||||
<p>
|
||||
<a name="fn-deferredlist"></a>
|
||||
<a class="mochidef reference" href="#fn-deferredlist">DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Combine a list of <a class="mochiref reference" href="#fn-deferred">Deferred</a> into one. Track the callbacks and
|
||||
return a list of (success, result) tuples, 'success' being a boolean
|
||||
indicating whether result is a normal result or an error.</p>
|
||||
<p>Once created, you have access to all <a class="mochiref reference" href="#fn-deferred">Deferred</a> methods, like
|
||||
addCallback, addErrback, addBoth. The behaviour can be changed by the
|
||||
following options:</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">fireOnOneCallback</span></tt>:</dt>
|
||||
<dd>Flag for launching the callback once the first Deferred of the list
|
||||
has returned.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">fireOnOneErrback</span></tt>:</dt>
|
||||
<dd>Flag for calling the errback at the first error of a Deferred.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">consumeErrors</span></tt>:</dt>
|
||||
<dd>Flag indicating that any errors raised in the Deferreds should be
|
||||
consumed by the DeferredList.</dd>
|
||||
</dl>
|
||||
<p>Example:</p>
|
||||
<pre class="literal-block">
|
||||
// We need to fetch data from 2 different urls
|
||||
var d1 = loadJSONDoc(url1);
|
||||
var d2 = loadJSONDoc(url2);
|
||||
var l1 = new DeferredList([d1, d2], false, false, true);
|
||||
l1.addCallback(function (resultList) {
|
||||
MochiKit.Base.map(function (result) {
|
||||
if (result[0]) {
|
||||
alert("Data is here: " + result[1]);
|
||||
} else {
|
||||
alert("Got an error: " + result[1]);
|
||||
}
|
||||
}, resultList);
|
||||
});
|
||||
</pre>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-calllater"></a>
|
||||
<a class="mochidef reference" href="#fn-calllater">callLater(seconds, func[, args...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func(args...)</span></tt> after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.
|
||||
This is a convenience method for:</p>
|
||||
<pre class="literal-block">
|
||||
func = partial.apply(extend(null, arguments, 1));
|
||||
return wait(seconds).addCallback(function (res) { return func() });
|
||||
</pre>
|
||||
<p>Returns a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-dosimplexmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-dosimplexmlhttprequest">doSimpleXMLHttpRequest(url[, queryArguments...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Perform a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> and wrap it with a
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> that may be cancelled.</p>
|
||||
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
|
||||
<dd>The URL to GET</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">queryArguments</span></tt>:</dt>
|
||||
<dd><p class="first">If this function is called with more than one argument, a <tt class="docutils literal"><span class="pre">"?"</span></tt>
|
||||
and the result of <a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a> with
|
||||
the rest of the arguments are appended to the URL.</p>
|
||||
<p>For example, this will do a GET request to the URL
|
||||
<tt class="docutils literal"><span class="pre">http://example.com?bar=baz</span></tt>:</p>
|
||||
<pre class="last literal-block">
|
||||
doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
|
||||
</pre>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
instance on success</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-evaljsonrequest"></a>
|
||||
<a class="mochidef reference" href="#fn-evaljsonrequest">evalJSONRequest(req)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Evaluate a JSON <a class="footnote-reference" href="#id10" id="id4" name="id4">[4]</a> <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
|
||||
<dd>The request whose <tt class="docutils literal"><span class="pre">.responseText</span></tt> property is to be evaluated</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A JavaScript object</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-fail"></a>
|
||||
<a class="mochidef reference" href="#fn-fail">fail([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.errback(result)</span></tt>
|
||||
called.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">succeed</span></tt> documentation for rationale.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
|
||||
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.errback">Deferred.prototype.errback(result)</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred()</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-gatherresults"></a>
|
||||
<a class="mochidef reference" href="#fn-gatherresults">gatherResults(deferreds)</a>:</p>
|
||||
<blockquote>
|
||||
A convenience function that returns a <a class="mochiref reference" href="#fn-deferredlist">DeferredList</a>
|
||||
from the given <tt class="docutils literal"><span class="pre">Array</span></tt> of <a class="mochiref reference" href="#fn-deferred">Deferred</a> instances
|
||||
that will callback with an <tt class="docutils literal"><span class="pre">Array</span></tt> of just results when
|
||||
they're available, or errback on the first array.</blockquote>
|
||||
<p>
|
||||
<a name="fn-getxmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-getxmlhttprequest">getXMLHttpRequest()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> compliant object for the current
|
||||
platform.</p>
|
||||
<p>In order of preference:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">XMLHttpRequest()</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP')</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Microsoft.XMLHTTP')</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">new</span> <span class="pre">ActiveXObject('Msxml2.XMLHTTP.4.0')</span></tt></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-maybedeferred"></a>
|
||||
<a class="mochidef reference" href="#fn-maybedeferred">maybeDeferred(func[, argument...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call a <tt class="docutils literal"><span class="pre">func</span></tt> with the given arguments and ensure the result is a
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">func</span></tt>:</dt>
|
||||
<dd>The function to call.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A new <a class="mochiref reference" href="#fn-deferred">Deferred</a> based on the call to <tt class="docutils literal"><span class="pre">func</span></tt>. If <tt class="docutils literal"><span class="pre">func</span></tt>
|
||||
does not naturally return a <a class="mochiref reference" href="#fn-deferred">Deferred</a>, its result or error
|
||||
value will be wrapped by one.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-loadjsondoc"></a>
|
||||
<a class="mochidef reference" href="#fn-loadjsondoc">loadJSONDoc(url)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Do a simple <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> to a URL and get the response
|
||||
as a JSON <a class="footnote-reference" href="#id10" id="id5" name="id5">[4]</a> document.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">url</span></tt>:</dt>
|
||||
<dd>The URL to GET</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the evaluated JSON <a class="footnote-reference" href="#id10" id="id6" name="id6">[4]</a>
|
||||
response upon successful <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-sendxmlhttprequest"></a>
|
||||
<a class="mochidef reference" href="#fn-sendxmlhttprequest">sendXMLHttpRequest(req[, sendContent])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Set an <tt class="docutils literal"><span class="pre">onreadystatechange</span></tt> handler on an <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object
|
||||
and send it off. Will return a cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will
|
||||
callback on success.</p>
|
||||
<p>Note that currently, only <tt class="docutils literal"><span class="pre">200</span></tt> (OK) and <tt class="docutils literal"><span class="pre">304</span></tt>
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an <tt class="docutils literal"><span class="pre">XMLHttpRequestError</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">req</span></tt>:</dt>
|
||||
<dd>An preconfigured <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt> object (open has been called).</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">sendContent</span></tt>:</dt>
|
||||
<dd>Optional string or DOM content to send over the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-deferred">Deferred</a> that will callback with the <tt class="docutils literal"><span class="pre">XMLHttpRequest</span></tt>
|
||||
instance on success.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-succeed"></a>
|
||||
<a class="mochidef reference" href="#fn-succeed">succeed([result])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-deferred">Deferred</a> that has already had <tt class="docutils literal"><span class="pre">.callback(result)</span></tt>
|
||||
called.</p>
|
||||
<p>This is useful when you're writing synchronous code to an asynchronous
|
||||
interface: i.e., some code is calling you expecting a <a class="mochiref reference" href="#fn-deferred">Deferred</a>
|
||||
result, but you don't actually need to do anything asynchronous. Just
|
||||
return <tt class="docutils literal"><span class="pre">succeed(theResult)</span></tt>.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">fail</span></tt> for a version of this function that uses a failing
|
||||
<a class="mochiref reference" href="#fn-deferred">Deferred</a> rather than a successful one.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">result</span></tt>:</dt>
|
||||
<dd>The result to give to <a class="mochiref reference" href="#fn-deferred.prototype.callback">Deferred.prototype.callback(result)</a></dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>a <tt class="docutils literal"><span class="pre">new</span></tt> <a class="mochiref reference" href="#fn-deferred">Deferred</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-wait"></a>
|
||||
<a class="mochidef reference" href="#fn-wait">wait(seconds[, res])</a>:</p>
|
||||
<blockquote>
|
||||
Return a new cancellable <a class="mochiref reference" href="#fn-deferred">Deferred</a> that will <tt class="docutils literal"><span class="pre">.callback(res)</span></tt>
|
||||
after at least <tt class="docutils literal"><span class="pre">seconds</span></tt> seconds have elapsed.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id7">[1]</a></td><td>AJAX, Asynchronous JavaScript and XML: <a class="reference" href="http://en.wikipedia.org/wiki/AJAX">http://en.wikipedia.org/wiki/AJAX</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id8">[2]</a></td><td>Twisted, an event-driven networking framework written in Python: <a class="reference" href="http://twistedmatrix.com/">http://twistedmatrix.com/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id9" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id3" name="id9">[3]</a></td><td>Twisted Deferred Reference: <a class="reference" href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html">http://twistedmatrix.com/projects/core/documentation/howto/defer.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id10" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id10">[4]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id6">3</a>)</em> JSON, JavaScript Object Notation: <a class="reference" href="http://json.org/">http://json.org/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,509 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Color - color abstraction with CSS3 support</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Color - color abstraction with CSS3 support</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// RGB color expressions are supported
|
||||
assert(
|
||||
objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
|
||||
);
|
||||
|
||||
// So is instantiating directly from HSL or RGB values.
|
||||
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
|
||||
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
|
||||
|
||||
// Or even SVG color keyword names, as per CSS3!
|
||||
assert( Color.fromString("aquamarine"), "#7fffd4" );
|
||||
|
||||
// NSColor-like colors built in
|
||||
assert( Color.whiteColor().toHexString() == "#ffffff" );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Color is an abstraction for handling colors and strings that
|
||||
represent colors.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<p>MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
|
||||
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
|
||||
color table.</p>
|
||||
<p>All of the functionality in this module is exposed through a Color constructor
|
||||
and its prototype, but a few of its internals are available for direct use at
|
||||
module level.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-color"></a>
|
||||
<a class="mochidef reference" href="#fn-color">Color()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Represents a color. Component values should be integers between <tt class="docutils literal"><span class="pre">0.0</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">1.0</span></tt>. You should use one of the <a class="mochiref reference" href="#fn-color">Color</a> factory
|
||||
functions such as <a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB</a>, <a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL</a>,
|
||||
etc. instead of constructing <a class="mochiref reference" href="#fn-color">Color</a> objects directly.</p>
|
||||
<p><a class="mochiref reference" href="#fn-color">Color</a> instances can be compared with
|
||||
<a class="mochiref reference" href="Base.html#fn-compare">MochiKit.Base.compare</a> (though ordering is on RGB, so is not
|
||||
particularly meaningful except for equality), and the default <tt class="docutils literal"><span class="pre">toString</span></tt>
|
||||
implementation returns <a class="mochiref reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-color">Color</a> instances are immutable, and much of the architecture is
|
||||
inspired by AppKit's NSColor <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a></p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.frombackground"></a>
|
||||
<a class="mochidef reference" href="#fn-color.frombackground">Color.fromBackground(elem)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the background of the provided
|
||||
element. Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
c = Color.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || Color.whiteColor();
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromcomputedstyle"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromcomputedstyle">Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the result of
|
||||
<a class="mochiref reference" href="DOM.html#fn-computedstyle">MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)</a>
|
||||
or <tt class="docutils literal"><span class="pre">null</span></tt> if not found.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhexstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhexstring">Color.fromHexString(hexString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given hexadecimal color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"#FFFFFF"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhsl"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhsl">Color.fromHSL(hue, saturation, lightness, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">lightness</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromhsl">Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhslstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhslstring">Color.fromHSLString(hslString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal hsl color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"hsl(0,0%,100%)"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
HSL values <tt class="docutils literal"><span class="pre">[0/360,</span> <span class="pre">0/360,</span> <span class="pre">360/360]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromhsv"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromhsv">Color.fromHSV(hue, saturation, value, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">hue</span></tt>, <tt class="docutils literal"><span class="pre">saturation</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">value</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0.0</span></tt> and
|
||||
<tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromhsv">Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromname"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromname">Color.fromName(colorName)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object corresponding to the given
|
||||
SVG 1.0 color keyword name <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> as per the W3C CSS3
|
||||
Color Module <a class="footnote-reference" href="#id8" id="id3" name="id3">[3]</a>. <tt class="docutils literal"><span class="pre">"transparent"</span></tt> is also accepted
|
||||
as a color name, and will return <a class="mochiref reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromrgb"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromrgb">Color.fromRGB(red, green, blue, alpha=1.0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a <a class="mochiref reference" href="#fn-color">Color</a> object from the given <tt class="docutils literal"><span class="pre">red</span></tt>, <tt class="docutils literal"><span class="pre">green</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">blue</span></tt>, and <tt class="docutils literal"><span class="pre">alpha</span></tt> values. Values should be numbers between <tt class="docutils literal"><span class="pre">0</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">alpha</span></tt> is not given, then <tt class="docutils literal"><span class="pre">1.0</span></tt> (completely opaque) will be used.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-color.fromrgb">Color.fromRGB({r: red, g: green, b: blue, a: alpha})</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromrgbstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromrgbstring">Color.fromRGBString(rgbString)</a>:</p>
|
||||
<blockquote>
|
||||
Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given decimal rgb color string.
|
||||
For example, <tt class="docutils literal"><span class="pre">"rgb(255,255,255)"</span></tt> would return a <a class="mochiref reference" href="#fn-color">Color</a> with
|
||||
RGB values <tt class="docutils literal"><span class="pre">[255/255,</span> <span class="pre">255/255,</span> <span class="pre">255/255]</span></tt> (white).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromtext"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromtext">Color.fromText(elem)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object based on the text color of the provided
|
||||
element. Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.fromstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.fromstring">Color.fromString(rgbOrHexString)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a <a class="mochiref reference" href="#fn-color">Color</a> object from the given RGB, HSL, hex, or name.
|
||||
Will return <tt class="docutils literal"><span class="pre">null</span></tt> if the string can not be parsed by any of these
|
||||
methods.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-color.fromhexstring">Color.fromHexString</a>, <a class="mochiref reference" href="#fn-color.fromrgbstring">Color.fromRGBString</a>,
|
||||
<a class="mochiref reference" href="#fn-color.fromhslstring">Color.fromHSLString</a> and <a class="mochiref reference" href="#fn-color.fromname">Color.fromName</a> more
|
||||
information.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.namedcolors"></a>
|
||||
<a class="mochidef reference" href="#fn-color.namedcolors">Color.namedColors()</a>:</p>
|
||||
<blockquote>
|
||||
Returns an object with properties for each SVG 1.0 color keyword
|
||||
name <a class="footnote-reference" href="#id7" id="id4" name="id4">[2]</a> supported by CSS3 <a class="footnote-reference" href="#id8" id="id5" name="id5">[3]</a>. Property names are the color keyword
|
||||
name in lowercase, and the value is a string suitable for
|
||||
<a class="mochiref reference" href="#fn-color.fromstring">Color.fromString()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithalpha"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithalpha">Color.prototype.colorWithAlpha(alpha)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">alpha</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithhue"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithhue">Color.prototype.colorWithHue(hue)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">hue</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithsaturation"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithsaturation">Color.prototype.colorWithSaturation(saturation)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">saturation</span></tt> value (using the HSL color model).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.colorwithlightness"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.colorwithlightness">Color.prototype.colorWithLightness(lightness)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but with the provided
|
||||
<tt class="docutils literal"><span class="pre">lightness</span></tt> value.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.darkercolorwithlevel"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.darkercolorwithlevel">Color.prototype.darkerColorWithLevel(level)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but darker by the given
|
||||
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.lightercolorwithlevel"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.lightercolorwithlevel">Color.prototype.lighterColorWithLevel(level)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> based on this color, but lighter by the given
|
||||
<tt class="docutils literal"><span class="pre">level</span></tt> (between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.blendedcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.blendedcolor">Color.prototype.blendedColor(other, fraction=0.5)</a>:</p>
|
||||
<blockquote>
|
||||
Return a new <a class="mochiref reference" href="#fn-color">Color</a> whose RGBA component values are a weighted sum
|
||||
of this color and <tt class="docutils literal"><span class="pre">other</span></tt>. Each component of the returned color
|
||||
is the <tt class="docutils literal"><span class="pre">fraction</span></tt> of other's value plus <tt class="docutils literal"><span class="pre">1</span> <span class="pre">-</span> <span class="pre">fraction</span></tt> of this
|
||||
color's.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.islight"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.islight">Color.prototype.isLight()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is greater than
|
||||
<tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
|
||||
are not premultiplied).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.isdark"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.isdark">Color.prototype.isDark()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return <tt class="docutils literal"><span class="pre">true</span></tt> if the lightness value of this color is less than or
|
||||
equal to <tt class="docutils literal"><span class="pre">0.5</span></tt>.</p>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">alpha</span></tt> is ignored for this calculation (color components
|
||||
are not premultiplied).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.torgbstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.torgbstring">Color.prototype.toRGBString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the decimal <tt class="docutils literal"><span class="pre">"rgb(red,</span> <span class="pre">green,</span> <span class="pre">blue)"</span></tt> string representation of this
|
||||
color.</p>
|
||||
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
|
||||
<tt class="docutils literal"><span class="pre">"rgba(red,</span> <span class="pre">green,</span> <span class="pre">blue,</span> <span class="pre">alpha)"</span></tt> string representation will be used.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.tohslstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.tohslstring">Color.prototype.toHSLString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the decimal <tt class="docutils literal"><span class="pre">"hsl(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness)"</span></tt>
|
||||
string representation of this color.</p>
|
||||
<p>If the alpha component is not <tt class="docutils literal"><span class="pre">1.0</span></tt> (fully opaque), the
|
||||
<tt class="docutils literal"><span class="pre">"hsla(hue,</span> <span class="pre">saturation,</span> <span class="pre">lightness,</span> <span class="pre">alpha)"</span></tt> string representation
|
||||
will be used.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.tohexstring"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.tohexstring">Color.prototype.toHexString()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the hexadecimal <tt class="docutils literal"><span class="pre">"#RRGGBB"</span></tt> string representation of this color.</p>
|
||||
<p>Note that the alpha component is completely ignored for hexadecimal
|
||||
string representations!</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
assert( Color.whiteColor().toHexString() == "#FFFFFF" );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.asrgb"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.asrgb">Color.prototype.asRGB()</a>:</p>
|
||||
<blockquote>
|
||||
Return the RGB (red, green, blue, alpha) components of this color as an
|
||||
object with <tt class="docutils literal"><span class="pre">r</span></tt>, <tt class="docutils literal"><span class="pre">g</span></tt>, <tt class="docutils literal"><span class="pre">b</span></tt>, and <tt class="docutils literal"><span class="pre">a</span></tt> properties that have
|
||||
values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.ashsl"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.ashsl">Color.prototype.asHSL()</a>:</p>
|
||||
<blockquote>
|
||||
Return the HSL (hue, saturation, lightness, alpha) components of this
|
||||
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">l</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
|
||||
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.prototype.ashsv"></a>
|
||||
<a class="mochidef reference" href="#fn-color.prototype.ashsv">Color.prototype.asHSV()</a>:</p>
|
||||
<blockquote>
|
||||
Return the HSV (hue, saturation, value, alpha) components of this
|
||||
color as an object with <tt class="docutils literal"><span class="pre">h</span></tt>, <tt class="docutils literal"><span class="pre">s</span></tt>, <tt class="docutils literal"><span class="pre">v</span></tt> and <tt class="docutils literal"><span class="pre">a</span></tt> properties
|
||||
that have values between <tt class="docutils literal"><span class="pre">0.0</span></tt> and <tt class="docutils literal"><span class="pre">1.0</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.blackcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.blackcolor">Color.blackColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 0
|
||||
(#000000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.bluecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.bluecolor">Color.blueColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 0, 1
|
||||
(#0000ff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.browncolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.browncolor">Color.brownColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.6, 0.4, 0.2
|
||||
(#996633).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.cyancolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.cyancolor">Color.cyanColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 1
|
||||
(#00ffff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.darkgraycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.darkgraycolor">Color.darkGrayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1/3, 1/3, 1/3
|
||||
(#555555).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.graycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.graycolor">Color.grayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0.5, 0.5
|
||||
(#808080).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.greencolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.greencolor">Color.greenColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0, 1, 0.
|
||||
(#00ff00).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.lightgraycolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.lightgraycolor">Color.lightGrayColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 2/3, 2/3, 2/3
|
||||
(#aaaaaa).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.magentacolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.magentacolor">Color.magentaColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 1
|
||||
(#ff00ff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.orangecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.orangecolor">Color.orangeColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0.5, 0
|
||||
(#ff8000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.purplecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.purplecolor">Color.purpleColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 0.5, 0, 0.5
|
||||
(#800080).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.redcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.redcolor">Color.redColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 0, 0
|
||||
(#ff0000).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.whitecolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.whitecolor">Color.whiteColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 1
|
||||
(#ffffff).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.yellowcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.yellowcolor">Color.yellowColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object whose RGB values are 1, 1, 0
|
||||
(#ffff00).</blockquote>
|
||||
<p>
|
||||
<a name="fn-color.transparentcolor"></a>
|
||||
<a class="mochidef reference" href="#fn-color.transparentcolor">Color.transparentColor()</a>:</p>
|
||||
<blockquote>
|
||||
Return a <a class="mochiref reference" href="#fn-color">Color</a> object that is completely transparent
|
||||
(has alpha component of 0).</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-clampcolorcomponent"></a>
|
||||
<a class="mochidef reference" href="#fn-clampcolorcomponent">clampColorComponent(num, scale)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns <tt class="docutils literal"><span class="pre">num</span> <span class="pre">*</span> <span class="pre">scale</span></tt> clamped between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">scale</span></tt>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-clampcolorcomponent">clampColorComponent</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-hsltorgb"></a>
|
||||
<a class="mochidef reference" href="#fn-hsltorgb">hslToRGB(hue, saturation, lightness, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes RGB values from the provided HSL values. The return value is a
|
||||
mapping with <tt class="docutils literal"><span class="pre">"r"</span></tt>, <tt class="docutils literal"><span class="pre">"g"</span></tt>, <tt class="docutils literal"><span class="pre">"b"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-hsltorgb">hslToRGB</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-hsvtorgb"></a>
|
||||
<a class="mochidef reference" href="#fn-hsvtorgb">hsvToRGB(hue, saturation, value, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes RGB values from the provided HSV values. The return value is a
|
||||
mapping with <tt class="docutils literal"><span class="pre">"r"</span></tt>, <tt class="docutils literal"><span class="pre">"g"</span></tt>, <tt class="docutils literal"><span class="pre">"b"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB({h: hue, s: saturation, v: value, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-hsvtorgb">hsvToRGB</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-tocolorpart"></a>
|
||||
<a class="mochidef reference" href="#fn-tocolorpart">toColorPart(num)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert num to a zero padded hexadecimal digit for use in a hexadecimal
|
||||
color string. Num should be an integer between <tt class="docutils literal"><span class="pre">0</span></tt> and <tt class="docutils literal"><span class="pre">255</span></tt>.</p>
|
||||
<p><a class="mochiref reference" href="#fn-tocolorpart">toColorPart</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rgbtohsl"></a>
|
||||
<a class="mochidef reference" href="#fn-rgbtohsl">rgbToHSL(red, green, blue, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes HSL values based on the provided RGB values. The return value is
|
||||
a mapping with <tt class="docutils literal"><span class="pre">"h"</span></tt>, <tt class="docutils literal"><span class="pre">"s"</span></tt>, <tt class="docutils literal"><span class="pre">"l"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL({r: red, g: green, b: blue, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-rgbtohsl">rgbToHSL</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rgbtohsv"></a>
|
||||
<a class="mochidef reference" href="#fn-rgbtohsv">rgbToHSV(red, green, blue, alpha)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Computes HSV values based on the provided RGB values. The return value is
|
||||
a mapping with <tt class="docutils literal"><span class="pre">"h"</span></tt>, <tt class="docutils literal"><span class="pre">"s"</span></tt>, <tt class="docutils literal"><span class="pre">"v"</span></tt> and <tt class="docutils literal"><span class="pre">"a"</span></tt> keys.</p>
|
||||
<dl class="docutils">
|
||||
<dt>Alternate form:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV({r: red, g: green, b: blue, a: alpha})</a>.</dd>
|
||||
</dl>
|
||||
<p><a class="mochiref reference" href="#fn-rgbtohsv">rgbToHSV</a> is not exported by default when using JSAN.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id7">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id8">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id5">2</a>)</em> W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,798 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.DOM - painless DOM manipulation API</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.DOM - painless DOM manipulation API</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
// put that in your document.createElement and smoke it!
|
||||
swapDOM(oldTable, newTable);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>As you probably know, the DOM APIs are some of the most painful Java-inspired
|
||||
APIs you'll run across from a highly dynamic language. Don't worry about that
|
||||
though, because they provide a reasonable basis to build something that
|
||||
sucks a lot less.</p>
|
||||
<p>MochiKit.DOM takes much of its inspiration from Nevow's <a class="footnote-reference" href="#id5" id="id1" name="id1">[1]</a> stan <a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a>.
|
||||
This means you choose a tag, give it some attributes, then stuff it full
|
||||
of <em>whatever objects you want</em>. MochiKit.DOM isn't stupid, it knows that
|
||||
a string should be a text node, and that you want functions to be called,
|
||||
and that <tt class="docutils literal"><span class="pre">Array</span></tt>-like objects should be expanded, and stupid <tt class="docutils literal"><span class="pre">null</span></tt> values
|
||||
should be skipped.</p>
|
||||
<p>Hell, it will let you return strings from functions, and use iterators from
|
||||
<a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>. If that's not enough, just teach it new tricks with
|
||||
<a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>. If you have never used an API like this for
|
||||
creating DOM elements, you've been wasting your damn time. Get with it!</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="dom-coercion-rules" name="dom-coercion-rules">DOM Coercion Rules</a></h2>
|
||||
<p>In order of precedence, <a class="mochiref reference" href="#fn-createdom">createDOM</a> coerces given arguments to DOM
|
||||
nodes using the following rules:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Functions are called with a <tt class="docutils literal"><span class="pre">this</span></tt> of the parent
|
||||
node and their return value is subject to the
|
||||
following rules (even this one).</li>
|
||||
<li><tt class="docutils literal"><span class="pre">undefined</span></tt> and <tt class="docutils literal"><span class="pre">null</span></tt> are ignored.</li>
|
||||
<li>Iterables (see <a class="mochiref reference" href="Iter.html">MochiKit.Iter</a>) are flattened
|
||||
(as if they were passed in-line as nodes) and each
|
||||
return value is subject to all of these rules.</li>
|
||||
<li>Values that look like DOM nodes (objects with a
|
||||
<tt class="docutils literal"><span class="pre">.nodeType</span> <span class="pre">></span> <span class="pre">0</span></tt>) are <tt class="docutils literal"><span class="pre">.appendChild</span></tt>'ed to the created
|
||||
DOM fragment.</li>
|
||||
<li>Strings are wrapped up with <tt class="docutils literal"><span class="pre">document.createTextNode</span></tt></li>
|
||||
<li>Objects that are not strings are run through the <tt class="docutils literal"><span class="pre">domConverters</span></tt>
|
||||
<a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
|
||||
(see <a class="mochiref reference" href="#fn-registerdomconverter">registerDOMConverter</a>).
|
||||
The value returned by the adapter is subject to these same rules (e.g.
|
||||
adapters are allowed to return a string, which will be coerced into a
|
||||
text node).</li>
|
||||
<li>If no adapter is available, <tt class="docutils literal"><span class="pre">.toString()</span></tt> is used to create a text node.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="creating-dom-element-trees" name="creating-dom-element-trees">Creating DOM Element Trees</a></h2>
|
||||
<p><a class="mochiref reference" href="#fn-createdom">createDOM</a> provides you with an excellent facility for creating DOM trees
|
||||
that is easy on the wrists. One of the best ways to understand how to use
|
||||
it is to take a look at an example:</p>
|
||||
<pre class="literal-block">
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
</pre>
|
||||
<p>This will create a table with the following visual layout (if it
|
||||
were inserted into the document DOM):</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="33%" />
|
||||
<col width="33%" />
|
||||
<col width="33%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">head1</th>
|
||||
<th class="head">head2</th>
|
||||
<th class="head">head3</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr><td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
<tr><td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>Corresponding to the following HTML:</p>
|
||||
<pre class="literal-block">
|
||||
<table class="prettytable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>head1</td>
|
||||
<td>head2</td>
|
||||
<td>head3</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="dom-context" name="dom-context">DOM Context</a></h2>
|
||||
<p>In order to prevent having to pass a <tt class="docutils literal"><span class="pre">window</span></tt> and/or <tt class="docutils literal"><span class="pre">document</span></tt>
|
||||
variable to every MochiKit.DOM function (e.g. when working with a
|
||||
child window), MochiKit.DOM maintains a context variable for each
|
||||
of them. They are managed with the <a class="mochiref reference" href="#fn-withwindow">withWindow</a> and
|
||||
<a class="mochiref reference" href="#fn-withdocument">withDocument</a> functions, and can be acquired with
|
||||
<a class="mochiref reference" href="#fn-currentwindow">currentWindow()</a> and <a class="mochiref reference" href="#fn-currentdocument">currentDocument()</a></p>
|
||||
<p>For example, if you are creating DOM nodes in a child window, you
|
||||
could do something like this:</p>
|
||||
<pre class="literal-block">
|
||||
withWindow(child, function () {
|
||||
var doc = currentDocument();
|
||||
appendChildNodes(doc.body, H1(null, "This is in the child!"));
|
||||
});
|
||||
</pre>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-withwindow">withWindow(win, ...)</a> also implies
|
||||
<a class="mochiref reference" href="#fn-withdocument">withDocument(win.document, ...)</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="element-visibility" name="element-visibility">Element Visibility</a></h2>
|
||||
<p>The <a class="mochiref reference" href="#fn-hideelement">hideElement</a> and <a class="mochiref reference" href="#fn-showelement">showElement</a> functions are
|
||||
provided as a convenience, but only work for elements that are
|
||||
<tt class="docutils literal"><span class="pre">display:</span> <span class="pre">block</span></tt>. For a general solution to showing, hiding, and checking
|
||||
the explicit visibility of elements, we recommend using a solution that
|
||||
involves a little CSS. Here's an example:</p>
|
||||
<pre class="literal-block">
|
||||
<style type="text/css">
|
||||
.invisible { display: none; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function toggleVisible(elem) {
|
||||
toggleElementClass("invisible", elem);
|
||||
}
|
||||
|
||||
function makeVisible(elem) {
|
||||
removeElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function makeInvisible(elem) {
|
||||
addElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function isVisible(elem) {
|
||||
// you may also want to check for
|
||||
// getElement(elem).style.display == "none"
|
||||
return !hasElementClass(elem, "invisible");
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
<p>MochiKit doesn't ship with such a solution, because there is no reliable and
|
||||
portable method for adding CSS rules on the fly with JavaScript.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-$"></a>
|
||||
<a class="mochidef reference" href="#fn-$">$(id[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
An alias for <a class="mochiref reference" href="#fn-getelement">getElement(id[, ...])</a></blockquote>
|
||||
<p>
|
||||
<a name="fn-addelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-addelementclass">addElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> has <tt class="docutils literal"><span class="pre">className</span></tt> set as part of its
|
||||
class attribute. This will not disturb other class names.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-addloadevent"></a>
|
||||
<a class="mochidef reference" href="#fn-addloadevent">addLoadEvent(func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-addloadevent">addLoadEvent</a> can not be used in combination with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> if the <tt class="docutils literal"><span class="pre">onload</span></tt> event is connected.
|
||||
Once an event is connected with <a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs
|
||||
may be used for that same event.</p>
|
||||
<p>This will stack <tt class="docutils literal"><span class="pre">window.onload</span></tt> functions on top of each other.
|
||||
Each function added will be called after <tt class="docutils literal"><span class="pre">onload</span></tt> in the
|
||||
order that they were added.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-addtocallstack"></a>
|
||||
<a class="mochidef reference" href="#fn-addtocallstack">addToCallStack(target, path, func[, once])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Note that <a class="mochiref reference" href="#fn-addtocallstack">addToCallStack</a> is not compatible with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>. Once an event is connected with
|
||||
<a class="mochiref reference" href="Signal.html">MochiKit.Signal</a>, no other APIs may be used for that same event.</p>
|
||||
<p>Set the property <tt class="docutils literal"><span class="pre">path</span></tt> of <tt class="docutils literal"><span class="pre">target</span></tt> to a function that calls the
|
||||
existing function at that property (if any), then calls <tt class="docutils literal"><span class="pre">func</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">target[path]()</span></tt> returns exactly <tt class="docutils literal"><span class="pre">false</span></tt>, then <tt class="docutils literal"><span class="pre">func</span></tt> will
|
||||
not be called.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">once</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then <tt class="docutils literal"><span class="pre">target[path]</span></tt> is set to <tt class="docutils literal"><span class="pre">null</span></tt> after
|
||||
the function call stack has completed.</p>
|
||||
<p>If called several times for the same <tt class="docutils literal"><span class="pre">target[path]</span></tt>, it will create
|
||||
a stack of functions (instead of just a pair).</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-appendchildnodes"></a>
|
||||
<a class="mochidef reference" href="#fn-appendchildnodes">appendChildNodes(node[, childNode[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Append children to a DOM element using the <a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to add children to
|
||||
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
|
||||
will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-computedstyle"></a>
|
||||
<a class="mochidef reference" href="#fn-computedstyle">computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)</a>:</p>
|
||||
<blockquote>
|
||||
Looks up a CSS property for the given element. The element can be
|
||||
specified as either a string with the element's ID or the element
|
||||
object itself.</blockquote>
|
||||
<p>
|
||||
<a name="fn-createdom"></a>
|
||||
<a class="mochidef reference" href="#fn-createdom">createDOM(name[, attrs[, node[, ...]]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Create a DOM fragment in a really convenient manner, much like
|
||||
Nevow`s <a class="footnote-reference" href="#id5" id="id3" name="id3">[1]</a> stan <a class="footnote-reference" href="#id6" id="id4" name="id4">[2]</a>.</p>
|
||||
<p>Partially applied versions of this function for common tags are
|
||||
available as aliases:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">A</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">BUTTON</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">BR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">CANVAS</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">DIV</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">FIELDSET</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">FORM</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H1</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H2</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">H3</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">HR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">IMG</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">INPUT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LABEL</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LEGEND</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">LI</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OL</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OPTGROUP</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">OPTION</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">P</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">PRE</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">SELECT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">SPAN</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">STRONG</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TABLE</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TBODY</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TD</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TEXTAREA</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TFOOT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TH</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">THEAD</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TR</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">TT</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">UL</span></tt></li>
|
||||
</ul>
|
||||
<p>See <a class="reference" href="#creating-dom-element-trees">Creating DOM Element Trees</a> for a comprehensive example.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">name</span></tt>:</dt>
|
||||
<dd>The kind of fragment to create (e.g. 'span'), such as you would
|
||||
pass to <tt class="docutils literal"><span class="pre">document.createElement</span></tt>.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd><p class="first">An object whose properties will be used as the attributes
|
||||
(e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">'display:block'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
|
||||
attributes need to be set.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a> for more information.</p>
|
||||
<p class="last">For convenience, if <tt class="docutils literal"><span class="pre">attrs</span></tt> is a string, <tt class="docutils literal"><span class="pre">null</span></tt> is used
|
||||
and the string will be considered the first <tt class="docutils literal"><span class="pre">node</span></tt>.</p>
|
||||
</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>A DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-createdomfunc"></a>
|
||||
<a class="mochidef reference" href="#fn-createdomfunc">createDOMFunc(tag[, attrs[, node[, ...]]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convenience function to create a partially applied createDOM
|
||||
function. You'd want to use this if you add additional convenience
|
||||
functions for creating tags, or if you find yourself creating
|
||||
a lot of tags with a bunch of the same attributes or contents.</p>
|
||||
<p>See <a class="mochiref reference" href="#fn-createdom">createDOM</a> for more detailed descriptions of the arguments.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">tag</span></tt>:</dt>
|
||||
<dd>The name of the tag</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd>Optionally specify the attributes to apply</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>...:</dt>
|
||||
<dd>Optionally specify any children nodes it should have</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>function that takes additional arguments and calls
|
||||
<a class="mochiref reference" href="#fn-createdom">createDOM</a></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-currentdocument"></a>
|
||||
<a class="mochidef reference" href="#fn-currentdocument">currentDocument()</a>:</p>
|
||||
<blockquote>
|
||||
Return the current <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
|
||||
be the same as the global <tt class="docutils literal"><span class="pre">document</span></tt> unless <a class="mochiref reference" href="#fn-withdocument">withDocument</a> or
|
||||
<a class="mochiref reference" href="#fn-withwindow">withWindow</a> is currently executing.</blockquote>
|
||||
<p>
|
||||
<a name="fn-currentwindow"></a>
|
||||
<a class="mochidef reference" href="#fn-currentwindow">currentWindow()</a>:</p>
|
||||
<blockquote>
|
||||
Return the current <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a>. This will always
|
||||
be the same as the global <tt class="docutils literal"><span class="pre">window</span></tt> unless <a class="mochiref reference" href="#fn-withwindow">withWindow</a> is
|
||||
currently executing.</blockquote>
|
||||
<p>
|
||||
<a name="fn-elementdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-elementdimensions">elementDimensions(element)</a>:</p>
|
||||
<blockquote>
|
||||
Return the absolute pixel width and height of <tt class="docutils literal"><span class="pre">element</span></tt> as an object with
|
||||
<tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt> is not in the
|
||||
document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object with
|
||||
<tt class="docutils literal"><span class="pre">w</span></tt> and/or <tt class="docutils literal"><span class="pre">h</span></tt> properties.</blockquote>
|
||||
<p>
|
||||
<a name="fn-elementposition"></a>
|
||||
<a class="mochidef reference" href="#fn-elementposition">elementPosition(element[, relativeTo={x: 0, y: 0}])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return the absolute pixel position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document as an
|
||||
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties, or <tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">element</span></tt>
|
||||
is not in the document. <tt class="docutils literal"><span class="pre">element</span></tt> may be specified as a string to
|
||||
be looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially
|
||||
as an object with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">relativeTo</span></tt> is given, then its coordinates are subtracted from
|
||||
the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt>, e.g.:</p>
|
||||
<pre class="literal-block">
|
||||
var elemPos = elementPosition(elem);
|
||||
var anotherElemPos = elementPosition(anotherElem);
|
||||
var relPos = elementPosition(elem, anotherElem);
|
||||
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
|
||||
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
|
||||
</pre>
|
||||
<p><tt class="docutils literal"><span class="pre">relativeTo</span></tt> may be specified as a string to be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, a DOM element, or trivially as an object
|
||||
with <tt class="docutils literal"><span class="pre">x</span></tt> and/or <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-emithtml"></a>
|
||||
<a class="mochidef reference" href="#fn-emithtml">emitHTML(dom[, lst])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert a DOM tree to an <tt class="docutils literal"><span class="pre">Array</span></tt> of HTML string fragments</p>
|
||||
<p>You probably want to use <a class="mochiref reference" href="#fn-tohtml">toHTML</a> instead.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-escapehtml"></a>
|
||||
<a class="mochidef reference" href="#fn-escapehtml">escapeHTML(s)</a>:</p>
|
||||
<blockquote>
|
||||
Make a string safe for HTML, converting the usual suspects (lt,
|
||||
gt, quot, apos, amp)</blockquote>
|
||||
<p>
|
||||
<a name="fn-focusonload"></a>
|
||||
<a class="mochidef reference" href="#fn-focusonload">focusOnLoad(element)</a>:</p>
|
||||
<blockquote>
|
||||
Add an onload event to focus the given element</blockquote>
|
||||
<p>
|
||||
<a name="fn-formcontents"></a>
|
||||
<a class="mochidef reference" href="#fn-formcontents">formContents(elem)</a>:</p>
|
||||
<blockquote>
|
||||
Search the DOM tree, starting at <tt class="docutils literal"><span class="pre">elem</span></tt>, for any elements with a
|
||||
<tt class="docutils literal"><span class="pre">name</span></tt> and <tt class="docutils literal"><span class="pre">value</span></tt> attribute. Return a 2-element <tt class="docutils literal"><span class="pre">Array</span></tt> of
|
||||
<tt class="docutils literal"><span class="pre">names</span></tt> and <tt class="docutils literal"><span class="pre">values</span></tt> suitable for use with
|
||||
<a class="mochiref reference" href="Base.html#fn-querystring">MochiKit.Base.queryString</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-getelement"></a>
|
||||
<a class="mochidef reference" href="#fn-getelement">getElement(id[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>A small quick little function to encapsulate the <tt class="docutils literal"><span class="pre">getElementById</span></tt>
|
||||
method. It includes a check to ensure we can use that method.</p>
|
||||
<p>If the id isn't a string, it will be returned as-is.</p>
|
||||
<p>Also available as <a class="mochiref reference" href="#fn-$">$(...)</a> for convenience and compatibility with
|
||||
other JavaScript frameworks.</p>
|
||||
<p>If multiple arguments are given, an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getelementsbytagandclassname"></a>
|
||||
<a class="mochidef reference" href="#fn-getelementsbytagandclassname">getElementsByTagAndClassName(tagName, className, parent=document)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns an array of elements in <tt class="docutils literal"><span class="pre">parent</span></tt> that match the tag name
|
||||
and class name provided. If <tt class="docutils literal"><span class="pre">parent</span></tt> is a string, it will be looked
|
||||
up with <a class="mochiref reference" href="#fn-getelement">getElement</a>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">tagName</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt> or <tt class="docutils literal"><span class="pre">"*"</span></tt>, all elements will be searched
|
||||
for the matching class.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">className</span></tt> is <tt class="docutils literal"><span class="pre">null</span></tt>, all elements matching the provided tag are
|
||||
returned.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getnodeattribute"></a>
|
||||
<a class="mochidef reference" href="#fn-getnodeattribute">getNodeAttribute(node, attr)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Get the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return <tt class="docutils literal"><span class="pre">null</span></tt> on exception).</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
|
||||
<dd><p class="first">The name of the attribute</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The attribute's value, or <tt class="docutils literal"><span class="pre">null</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-getviewportdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-getviewportdimensions">getViewportDimensions()</a>:</p>
|
||||
<blockquote>
|
||||
Return the pixel width and height of the viewport as an object with <tt class="docutils literal"><span class="pre">w</span></tt>
|
||||
and <tt class="docutils literal"><span class="pre">h</span></tt> properties. <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-haselementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-haselementclass">hasElementClass(element, className[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">className</span></tt> is found on the <tt class="docutils literal"><span class="pre">element</span></tt>.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-hideelement"></a>
|
||||
<a class="mochidef reference" href="#fn-hideelement">hideElement(element, ...)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
|
||||
<pre class="literal-block">
|
||||
partial(setDisplayForElement, "none")
|
||||
</pre>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-registerdomconverter"></a>
|
||||
<a class="mochidef reference" href="#fn-registerdomconverter">registerDOMConverter(name, check, wrap[, override])</a>:</p>
|
||||
<blockquote>
|
||||
Register an adapter to convert objects that match <tt class="docutils literal"><span class="pre">check(obj,</span> <span class="pre">ctx)</span></tt>
|
||||
to a DOM element, or something that can be converted to a DOM
|
||||
element (i.e. number, bool, string, function, iterable).</blockquote>
|
||||
<p>
|
||||
<a name="fn-removeelement"></a>
|
||||
<a class="mochidef reference" href="#fn-removeelement">removeElement(node)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Remove and return <tt class="docutils literal"><span class="pre">node</span></tt> from a DOM tree. This is technically
|
||||
just a convenience for <a class="mochiref reference" href="#fn-swapdom">swapDOM(node, null)</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>the DOM element (or string id of one) to be removed</dd>
|
||||
<dt><em>returns</em></dt>
|
||||
<dd>The removed element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-removeelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-removeelementclass">removeElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Ensure that the given <tt class="docutils literal"><span class="pre">element</span></tt> does not have <tt class="docutils literal"><span class="pre">className</span></tt> set as part
|
||||
of its class attribute. This will not disturb other class names.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-replacechildnodes"></a>
|
||||
<a class="mochidef reference" href="#fn-replacechildnodes">replaceChildNodes(node[, childNode[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Remove all children from the given DOM element, then append any given
|
||||
childNodes to it (by calling <a class="mochiref reference" href="#fn-appendchildnodes">appendChildNodes</a>).</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to add children to
|
||||
(if a string is given, <a class="mochiref reference" href="#fn-getelement">getElement(node)</a>
|
||||
will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">childNode</span></tt>...:</dt>
|
||||
<dd>All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
<a class="reference" href="#dom-coercion-rules">DOM Coercion Rules</a>.</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-scrapetext"></a>
|
||||
<a class="mochidef reference" href="#fn-scrapetext">scrapeText(node[, asArray=false])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Walk a DOM tree in-order and scrape all of the text out of it as a
|
||||
<tt class="docutils literal"><span class="pre">string</span></tt>.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">asArray</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then an <tt class="docutils literal"><span class="pre">Array</span></tt> will be returned with
|
||||
each individual text node. These two are equivalent:</p>
|
||||
<pre class="literal-block">
|
||||
assert( scrapeText(node) == scrapeText(node, true).join("") );
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setdisplayforelement"></a>
|
||||
<a class="mochidef reference" href="#fn-setdisplayforelement">setDisplayForElement(display, element[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Change the <tt class="docutils literal"><span class="pre">style.display</span></tt> for the given element(s). Usually
|
||||
used as the partial forms:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="#fn-showelement">showElement(element, ...)</a></li>
|
||||
<li><a class="mochiref reference" href="#fn-hideelement">hideElement(element, ...)</a></li>
|
||||
</ul>
|
||||
<p>Elements are looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are acceptable.</p>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementclass">setElementClass(element, className)</a>:</p>
|
||||
<blockquote>
|
||||
Set the entire class attribute of <tt class="docutils literal"><span class="pre">element</span></tt> to <tt class="docutils literal"><span class="pre">className</span></tt>.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementdimensions"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementdimensions">setElementDimensions(element, dimensions[, units='px'])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Sets the dimensions of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
|
||||
object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">dimensions</span></tt>:</dt>
|
||||
<dd>An object with <tt class="docutils literal"><span class="pre">w</span></tt> and <tt class="docutils literal"><span class="pre">h</span></tt> properties</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
|
||||
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setelementposition"></a>
|
||||
<a class="mochidef reference" href="#fn-setelementposition">setElementPosition(element, position[, units='px'])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Sets the absolute position of <tt class="docutils literal"><span class="pre">element</span></tt> in the document from an
|
||||
object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">position</span></tt>:</dt>
|
||||
<dd>An object with <tt class="docutils literal"><span class="pre">x</span></tt> and <tt class="docutils literal"><span class="pre">y</span></tt> properties</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">units</span></tt>:</dt>
|
||||
<dd>Optionally set the units to use, default is <tt class="docutils literal"><span class="pre">px</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setnodeattribute"></a>
|
||||
<a class="mochidef reference" href="#fn-setnodeattribute">setNodeAttribute(node, attr, value)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Set the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return null on exception). If
|
||||
setting more than one attribute, you should use
|
||||
<a class="mochiref reference" href="#fn-updatenodeattributes">updateNodeAttributes</a>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attr</span></tt>:</dt>
|
||||
<dd><p class="first">The name of the attribute</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself.</p>
|
||||
</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">value</span></tt>:</dt>
|
||||
<dd>The value of the attribute, may be an object to be merged
|
||||
(e.g. for setting style).</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element or <tt class="docutils literal"><span class="pre">null</span></tt> on failure</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-setopacity"></a>
|
||||
<a class="mochidef reference" href="#fn-setopacity">setOpacity(element, opacity)</a>:</p>
|
||||
<blockquote>
|
||||
Sets <tt class="docutils literal"><span class="pre">opacity</span></tt> for <tt class="docutils literal"><span class="pre">element</span></tt>. Valid <tt class="docutils literal"><span class="pre">opacity</span></tt> values range from 0
|
||||
(invisible) to 1 (opaque). <tt class="docutils literal"><span class="pre">element</span></tt> is looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-showelement"></a>
|
||||
<a class="mochidef reference" href="#fn-showelement">showElement(element, ...)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Partial form of <a class="mochiref reference" href="#fn-setdisplayforelement">setDisplayForElement</a>, specifically:</p>
|
||||
<pre class="literal-block">
|
||||
partial(setDisplayForElement, "block")
|
||||
</pre>
|
||||
<p>For information about the caveats of using a <tt class="docutils literal"><span class="pre">style.display</span></tt> based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
<a class="reference" href="#element-visibility">Element Visibility</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-swapdom"></a>
|
||||
<a class="mochidef reference" href="#fn-swapdom">swapDOM(dest, src)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Replace <tt class="docutils literal"><span class="pre">dest</span></tt> in a DOM tree with <tt class="docutils literal"><span class="pre">src</span></tt>, returning <tt class="docutils literal"><span class="pre">src</span></tt>.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">dest</span></tt>:</dt>
|
||||
<dd>a DOM element (or string id of one) to be replaced</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">src</span></tt>:</dt>
|
||||
<dd>the DOM element (or string id of one) to replace it with, or
|
||||
<tt class="docutils literal"><span class="pre">null</span></tt> if <tt class="docutils literal"><span class="pre">dest</span></tt> is to be removed (replaced with nothing).</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>a DOM element (<tt class="docutils literal"><span class="pre">src</span></tt>)</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-swapelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-swapelementclass">swapElementClass(element, fromClass, toClass)</a>:</p>
|
||||
<blockquote>
|
||||
If <tt class="docutils literal"><span class="pre">fromClass</span></tt> is set on <tt class="docutils literal"><span class="pre">element</span></tt>, replace it with <tt class="docutils literal"><span class="pre">toClass</span></tt>.
|
||||
This will not disturb other classes on that element.
|
||||
<tt class="docutils literal"><span class="pre">element</span></tt> is looked up with <a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers
|
||||
are also acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-toggleelementclass"></a>
|
||||
<a class="mochidef reference" href="#fn-toggleelementclass">toggleElementClass(className[, element[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Toggle the presence of a given <tt class="docutils literal"><span class="pre">className</span></tt> in the class attribute
|
||||
of all given elements. All elements will be looked up with
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement</a>, so string identifiers are acceptable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-tohtml"></a>
|
||||
<a class="mochidef reference" href="#fn-tohtml">toHTML(dom)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a DOM tree to a HTML string using <a class="mochiref reference" href="#fn-emithtml">emitHTML</a></blockquote>
|
||||
<p>
|
||||
<a name="fn-updatenodeattributes"></a>
|
||||
<a class="mochidef reference" href="#fn-updatenodeattributes">updateNodeAttributes(node, attrs)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Update the attributes of a DOM element from a given object.</p>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">node</span></tt>:</dt>
|
||||
<dd>A reference to the DOM element to update (if a string is given,
|
||||
<a class="mochiref reference" href="#fn-getelement">getElement(node)</a> will be used to locate the node)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">attrs</span></tt>:</dt>
|
||||
<dd><p class="first">An object whose properties will be used to set the attributes
|
||||
(e.g. <tt class="docutils literal"><span class="pre">{'class':</span> <span class="pre">'invisible'}</span></tt>), or <tt class="docutils literal"><span class="pre">null</span></tt> if no
|
||||
attributes need to be set. If an object is given for the
|
||||
attribute value (e.g. <tt class="docutils literal"><span class="pre">{'style':</span> <span class="pre">{'display':</span> <span class="pre">'block'}}</span></tt>)
|
||||
then <a class="mochiref reference" href="Base.html#fn-updatetree">MochiKit.Base.updatetree</a> will be used to set that
|
||||
attribute.</p>
|
||||
<p class="last">Note that it will do the right thing for IE, so don't do
|
||||
the <tt class="docutils literal"><span class="pre">class</span></tt> -> <tt class="docutils literal"><span class="pre">className</span></tt> hack yourself, and it deals with
|
||||
setting "on..." event handlers correctly.</p>
|
||||
</dd>
|
||||
<dt><em>returns</em>:</dt>
|
||||
<dd>The given DOM element</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-withwindow"></a>
|
||||
<a class="mochidef reference" href="#fn-withwindow">withWindow(win, func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">window</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win</span></tt> and
|
||||
the <tt class="docutils literal"><span class="pre">document</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">win.document</span></tt>. When
|
||||
<tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a> will be
|
||||
restored to its previous state.</p>
|
||||
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-withdocument"></a>
|
||||
<a class="mochidef reference" href="#fn-withdocument">withDocument(doc, func)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Call <tt class="docutils literal"><span class="pre">func</span></tt> with the <tt class="docutils literal"><span class="pre">doc</span></tt> <a class="reference" href="#dom-context">DOM Context</a> set to <tt class="docutils literal"><span class="pre">doc</span></tt>.
|
||||
When <tt class="docutils literal"><span class="pre">func()</span></tt> returns or throws an error, the <a class="reference" href="#dom-context">DOM Context</a>
|
||||
will be restored to its previous state.</p>
|
||||
<p>The return value of <tt class="docutils literal"><span class="pre">func()</span></tt> is returned by this function.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id5">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Nevow, a web application construction kit for Python: <a class="reference" href="http://nevow.com/">http://nevow.com/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id6">[2]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> nevow.stan is a domain specific language for Python
|
||||
(read as "crazy getitem/call overloading abuse") that Donovan and I
|
||||
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
|
||||
(David Abrahams) hotel room. Donovan later inflicted this upon the
|
||||
masses in Nevow. Check out the Divmod project page for some
|
||||
examples: <a class="reference" href="http://nevow.com/Nevow2004Tutorial.html">http://nevow.com/Nevow2004Tutorial.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.DateTime - "what time is it anyway?"</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.DateTime - "what time is it anyway?"</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
stringDate = toISOTimestamp(new Date());
|
||||
dateObject = isoTimestamp(stringDate);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Remote servers don't give you JavaScript Date objects, and they certainly
|
||||
don't want them from you, so you need to deal with string representations
|
||||
of dates and timestamps. MochiKit.Date does that.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<p>None.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-isodate"></a>
|
||||
<a class="mochidef reference" href="#fn-isodate">isoDate(str)</a>:</p>
|
||||
<blockquote>
|
||||
Convert an ISO 8601 date (YYYY-MM-DD) to a <tt class="docutils literal"><span class="pre">Date</span></tt> object.</blockquote>
|
||||
<p>
|
||||
<a name="fn-isotimestamp"></a>
|
||||
<a class="mochidef reference" href="#fn-isotimestamp">isoTimestamp(str)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert any ISO 8601 <a class="footnote-reference" href="#id3" id="id1" name="id1">[1]</a> timestamp (or something reasonably close to it)
|
||||
to a <tt class="docutils literal"><span class="pre">Date</span></tt> object. Will accept the "de facto" form:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DD hh:mm:ss</blockquote>
|
||||
<p>or (the proper form):</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DDThh:mm:ssZ</blockquote>
|
||||
<p>If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the
|
||||
local timezone is used.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisotime"></a>
|
||||
<a class="mochidef reference" href="#fn-toisotime">toISOTime(date)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to a string in the form of hh:mm:ss</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisotimestamp"></a>
|
||||
<a class="mochidef reference" href="#fn-toisotimestamp">toISOTimestamp(date, realISO=false)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to something that's ALMOST but not quite an
|
||||
ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DDThh:mm:ssZ</blockquote>
|
||||
<p>However, we see junk in SQL and other places that looks like this:</p>
|
||||
<blockquote>
|
||||
YYYY-MM-DD hh:mm:ss</blockquote>
|
||||
<p>So, this function returns the latter form, despite its name, unless
|
||||
you pass <tt class="docutils literal"><span class="pre">true</span></tt> for <tt class="docutils literal"><span class="pre">realISO</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-toisodate"></a>
|
||||
<a class="mochidef reference" href="#fn-toisodate">toISODate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Convert a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an ISO 8601 <a class="footnote-reference" href="#id3" id="id2" name="id2">[1]</a> date string (YYYY-MM-DD)</blockquote>
|
||||
<p>
|
||||
<a name="fn-americandate"></a>
|
||||
<a class="mochidef reference" href="#fn-americandate">americanDate(str)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a MM/DD/YYYY date to a <tt class="docutils literal"><span class="pre">Date</span></tt> object</blockquote>
|
||||
<p>
|
||||
<a name="fn-topaddedamericandate"></a>
|
||||
<a class="mochidef reference" href="#fn-topaddedamericandate">toPaddedAmericanDate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an MM/DD/YYYY date, e.g. 01/01/2001</blockquote>
|
||||
<p>
|
||||
<a name="fn-toamericandate"></a>
|
||||
<a class="mochidef reference" href="#fn-toamericandate">toAmericanDate(date)</a>:</p>
|
||||
<blockquote>
|
||||
Converts a <tt class="docutils literal"><span class="pre">Date</span></tt> object to an M/D/YYYY date, e.g. 1/1/2001</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id3" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id3">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>)</em> W3C profile of ISO 8601: <a class="reference" href="http://www.w3.org/TR/NOTE-datetime">http://www.w3.org/TR/NOTE-datetime</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,241 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Format - string formatting goes here</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Format - string formatting goes here</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
assert( truncToFixed(0.12345, 4) == "0.1234" );
|
||||
assert( roundToFixed(0.12345, 4) == "0.1235" );
|
||||
assert( twoDigitAverage(1, 0) == "0" );
|
||||
assert( twoDigitFloat(1.2345) == "1.23" );
|
||||
assert( twoDigitFloat(1) == "1" );
|
||||
assert( percentFormat(1.234567) == "123.46%" );
|
||||
assert( numberFormatter("###,###%")(125) == "12,500%" );
|
||||
assert( numberFormatter("##.000")(1.25) == "1.250" );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Formatting strings and stringifying numbers is boring, so a couple useful
|
||||
functions in that domain live here.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<p>None.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="formatting-numbers" name="formatting-numbers">Formatting Numbers</a></h2>
|
||||
<p>MochiKit provides an extensible number formatting facility, modeled loosely
|
||||
after the Number Format Pattern Syntax <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a> from Java.
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter(pattern[, placeholder=""[, locale="default"])</a>
|
||||
returns a function that converts Number to string using the given information.
|
||||
<tt class="docutils literal"><span class="pre">pattern</span></tt> is a string consisting of the following symbols:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<thead valign="bottom">
|
||||
<tr><th class="head">Symbol</th>
|
||||
<th class="head">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<tr><td><tt class="docutils literal"><span class="pre">-</span></tt></td>
|
||||
<td>If given, used as the position of the minus sign
|
||||
for negative numbers. If not given, the position
|
||||
to the left of the first number placeholder is used.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">#</span></tt></td>
|
||||
<td>The placeholder for a number that does not imply zero
|
||||
padding.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">0</span></tt></td>
|
||||
<td>The placeholder for a number that implies zero padding.
|
||||
If it is used to the right of a decimal separator, it
|
||||
implies trailing zeros, otherwise leading zeros.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">,</span></tt></td>
|
||||
<td>The placeholder for a "thousands separator". May be used
|
||||
at most once, and it must be to the left of a decimal
|
||||
separator. Will be replaced by <tt class="docutils literal"><span class="pre">locale.separator</span></tt> in the
|
||||
result (the default is also <tt class="docutils literal"><span class="pre">,</span></tt>).</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">.</span></tt></td>
|
||||
<td>The decimal separator. The quantity of <tt class="docutils literal"><span class="pre">#</span></tt> or <tt class="docutils literal"><span class="pre">0</span></tt>
|
||||
after the decimal separator will determine the precision of
|
||||
the result. If no decimal separator is present, the
|
||||
fractional precision is <tt class="docutils literal"><span class="pre">0</span></tt> -- meaning that it will be
|
||||
rounded to the nearest integer.</td>
|
||||
</tr>
|
||||
<tr><td><tt class="docutils literal"><span class="pre">%</span></tt></td>
|
||||
<td>If present, the number will be multiplied by <tt class="docutils literal"><span class="pre">100</span></tt> and
|
||||
the <tt class="docutils literal"><span class="pre">%</span></tt> will be replaced by <tt class="docutils literal"><span class="pre">locale.percent</span></tt>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-formatlocale"></a>
|
||||
<a class="mochidef reference" href="#fn-formatlocale">formatLocale(locale="default")</a>:</p>
|
||||
<blockquote>
|
||||
Return a locale object for the given locale. <tt class="docutils literal"><span class="pre">locale</span></tt> may be either a
|
||||
string, which is looked up in the <tt class="docutils literal"><span class="pre">MochiKit.Format.LOCALE</span></tt> object, or
|
||||
a locale object. If no locale is given, <tt class="docutils literal"><span class="pre">LOCALE.default</span></tt> is used
|
||||
(equivalent to <tt class="docutils literal"><span class="pre">LOCALE.en_US</span></tt>).</blockquote>
|
||||
<p>
|
||||
<a name="fn-lstrip"></a>
|
||||
<a class="mochidef reference" href="#fn-lstrip">lstrip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading whitespace stripped.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-numberformatter"></a>
|
||||
<a class="mochidef reference" href="#fn-numberformatter">numberFormatter(pattern, placeholder="", locale="default")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a function <tt class="docutils literal"><span class="pre">formatNumber(aNumber)</span></tt> that formats numbers
|
||||
as a string according to the given pattern, placeholder and locale.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">pattern</span></tt> is a string that describes how the numbers should be formatted,
|
||||
for more information see <a class="reference" href="#formatting-numbers">Formatting Numbers</a>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">locale</span></tt> is a string of a known locale (en_US, de_DE, fr_FR, default) or
|
||||
an object with the following fields:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="16%" />
|
||||
<col width="84%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>separator</td>
|
||||
<td>The "thousands" separator for this locale (en_US is ",")</td>
|
||||
</tr>
|
||||
<tr><td>decimal</td>
|
||||
<td>The decimal separator for this locale (en_US is ".")</td>
|
||||
</tr>
|
||||
<tr><td>percent</td>
|
||||
<td>The percent symbol for this locale (en_US is "%")</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-percentformat"></a>
|
||||
<a class="mochidef reference" href="#fn-percentformat">percentFormat(someFloat)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf("%.2f%%",</span> <span class="pre">someFloat</span> <span class="pre">*</span> <span class="pre">100)</span></tt></p>
|
||||
<p>In new code, you probably want to use:
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter("#.##%")(someFloat)</a> instead.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-roundtofixed"></a>
|
||||
<a class="mochidef reference" href="#fn-roundtofixed">roundToFixed(aNumber, precision)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, rounded to <tt class="docutils literal"><span class="pre">precision</span></tt>
|
||||
digits with trailing zeros. This is similar to
|
||||
<tt class="docutils literal"><span class="pre">Number.toFixed(aNumber,</span> <span class="pre">precision)</span></tt>, but this has implementation
|
||||
consistent rounding behavior (some versions of Safari round 0.5 down!)
|
||||
and also includes preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt> (Safari,
|
||||
again).</p>
|
||||
<p>For example, <a class="mochiref reference" href="#fn-roundtofixed">roundToFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.14</span></tt> on every
|
||||
supported platform, where some return <tt class="docutils literal"><span class="pre">.13</span></tt> for <tt class="docutils literal"><span class="pre">(0.1357).toFixed(2)</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-rstrip"></a>
|
||||
<a class="mochidef reference" href="#fn-rstrip">rstrip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with trailing whitespace stripped.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-strip"></a>
|
||||
<a class="mochidef reference" href="#fn-strip">strip(str, chars="\s")</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns a string based on <tt class="docutils literal"><span class="pre">str</span></tt> with leading and trailing whitespace
|
||||
stripped (equivalent to <a class="mochiref reference" href="#fn-lstrip">lstrip(rstrip(str, chars), chars)</a>).</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">chars</span></tt> is given, then that expression will be used instead of
|
||||
whitespace. <tt class="docutils literal"><span class="pre">chars</span></tt> should be a string suitable for use in a <tt class="docutils literal"><span class="pre">RegExp</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">[character</span> <span class="pre">set]</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-trunctofixed"></a>
|
||||
<a class="mochidef reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return a string representation of <tt class="docutils literal"><span class="pre">aNumber</span></tt>, truncated to <tt class="docutils literal"><span class="pre">precision</span></tt>
|
||||
digits with trailing zeros. This is similar to
|
||||
<tt class="docutils literal"><span class="pre">aNumber.toFixed(precision)</span></tt>, but this truncates rather than rounds and
|
||||
has implementation consistent behavior for numbers less than 1.
|
||||
Specifically, <a class="mochiref reference" href="#fn-trunctofixed">truncToFixed(aNumber, precision)</a> will always have a
|
||||
preceding <tt class="docutils literal"><span class="pre">0</span></tt> for numbers less than <tt class="docutils literal"><span class="pre">1</span></tt>.</p>
|
||||
<p>For example, <a class="mochiref reference" href="#fn-tofixed">toFixed(0.1357, 2)</a> returns <tt class="docutils literal"><span class="pre">0.13</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-twodigitaverage"></a>
|
||||
<a class="mochidef reference" href="#fn-twodigitaverage">twoDigitAverage(numerator, denominator)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Calculate an average from a numerator and a denominator and return
|
||||
it as a string with two digits of precision (e.g. "1.23").</p>
|
||||
<p>If the denominator is 0, "0" will be returned instead of <tt class="docutils literal"><span class="pre">NaN</span></tt>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-twodigitfloat"></a>
|
||||
<a class="mochidef reference" href="#fn-twodigitfloat">twoDigitFloat(someFloat)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Roughly equivalent to: <tt class="docutils literal"><span class="pre">sprintf("%.2f",</span> <span class="pre">someFloat)</span></tt></p>
|
||||
<p>In new code, you probably want to use
|
||||
<a class="mochiref reference" href="#fn-numberformatter">numberFormatter("#.##")(someFloat)</a> instead.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id2" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>Java Number Format Pattern Syntax:
|
||||
<a class="reference" href="http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html">http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,372 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
theSum = sum(takewhile(
|
||||
partial(operator.gt, 10),
|
||||
imap(
|
||||
partial(operator.mul, 2),
|
||||
count()
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>All of the functional programming missing from <a class="mochiref reference" href="Base.html">MochiKit.Base</a> lives
|
||||
here. The functionality in this module is largely inspired by Python's iteration
|
||||
protocol <a class="footnote-reference" href="#id4" id="id1" name="id1">[1]</a>, and the itertools module <a class="footnote-reference" href="#id5" id="id2" name="id2">[2]</a>.</p>
|
||||
<p>MochiKit.Iter defines a standard way to iterate over anything, that you can
|
||||
extend with <a class="mochiref reference" href="#fn-registeriterator">registerIterator</a>, or by implementing the <tt class="docutils literal"><span class="pre">.iter()</span></tt>
|
||||
protocol. Iterators are lazy, so it can potentially be cheaper to build a
|
||||
filter chain of iterators than to build lots of intermediate arrays.
|
||||
Especially when the data set is very large, but the result is not.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="iteration-for-javascript" name="iteration-for-javascript">Iteration for JavaScript</a></h2>
|
||||
<p>The best overview right now is in my Iteration for JavaScript <a class="footnote-reference" href="#id6" id="id3" name="id3">[3]</a> blog entry.
|
||||
This information will migrate here eventually.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="errors" name="errors">Errors</a></h2>
|
||||
<p>
|
||||
<a name="fn-stopiteration"></a>
|
||||
<a class="mochidef reference" href="#fn-stopiteration">StopIteration</a>:</p>
|
||||
<blockquote>
|
||||
The singleton <a class="mochiref reference" href="Base.html#fn-namederror">MochiKit.Base.NamedError</a> that signifies the end
|
||||
of an iterator</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-applymap"></a>
|
||||
<a class="mochidef reference" href="#fn-applymap">applymap(fun, seq[, self])</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">applymap(fun,</span> <span class="pre">seq)</span></tt> --></dt>
|
||||
<dd>fun.apply(self, seq0), fun.apply(self, seq1), ...</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-chain"></a>
|
||||
<a class="mochidef reference" href="#fn-chain">chain(p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">chain(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> p0, p1, ... plast, q0, q1, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-count"></a>
|
||||
<a class="mochidef reference" href="#fn-count">count(n=0)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">count(n=0)</span></tt> --> n, n + 1, n + 2, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-cycle"></a>
|
||||
<a class="mochidef reference" href="#fn-cycle">cycle(p)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">cycle(p)</span></tt> --> p0, p1, ... plast, p0, p1, ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-dropwhile"></a>
|
||||
<a class="mochidef reference" href="#fn-dropwhile">dropwhile(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">dropwhile(pred,</span> <span class="pre">seq)</span></tt> --> seq[n], seq[n + 1], starting when</dt>
|
||||
<dd>pred(seq[n]) fails</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-every"></a>
|
||||
<a class="mochidef reference" href="#fn-every">every(iterable, func)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for every item in
|
||||
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-exhaust"></a>
|
||||
<a class="mochidef reference" href="#fn-exhaust">exhaust(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Exhausts an iterable without saving the results anywhere,
|
||||
like <a class="mochiref reference" href="#fn-list">list(iterable)</a> when you don't care what the output is.</blockquote>
|
||||
<p>
|
||||
<a name="fn-foreach"></a>
|
||||
<a class="mochidef reference" href="#fn-foreach">forEach(iterable, func[, self])</a>:</p>
|
||||
<blockquote>
|
||||
Call <tt class="docutils literal"><span class="pre">func</span></tt> for each item in <tt class="docutils literal"><span class="pre">iterable</span></tt>, and don't save the results.</blockquote>
|
||||
<p>
|
||||
<a name="fn-groupby"></a>
|
||||
<a class="mochidef reference" href="#fn-groupby">groupby(iterable[, keyfunc])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Make an iterator that returns consecutive keys and groups from the
|
||||
iterable. The key is a function computing a key value for each element.
|
||||
If not specified or is None, key defaults to an identity function and
|
||||
returns the element unchanged. Generally, the iterable needs to already be
|
||||
sorted on the same key function.</p>
|
||||
<p>The returned group is itself an iterator that shares the underlying
|
||||
iterable with <a class="mochiref reference" href="#fn-groupby">groupby()</a>. Because the source is shared, when the
|
||||
groupby object is advanced, the previous group is no longer visible.
|
||||
So, if that data is needed later, it should be stored as an array:</p>
|
||||
<pre class="literal-block">
|
||||
var groups = [];
|
||||
var uniquekeys = [];
|
||||
forEach(groupby(data, keyfunc), function (key_group) {
|
||||
groups.push(list(key_group[1]));
|
||||
uniquekeys.push(key_group[0]);
|
||||
});
|
||||
</pre>
|
||||
<p>As a convenience, <a class="mochiref reference" href="#fn-groupby_as_array">groupby_as_array()</a> is provided to suit the above
|
||||
use case.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-groupby_as_array"></a>
|
||||
<a class="mochidef reference" href="#fn-groupby_as_array">groupby_as_array(iterable[, keyfunc])</a>:</p>
|
||||
<blockquote>
|
||||
Perform the same task as <a class="mochiref reference" href="#fn-groupby">groupby()</a>, except return an array of
|
||||
arrays instead of an iterator of iterators.</blockquote>
|
||||
<p>
|
||||
<a name="fn-iextend"></a>
|
||||
<a class="mochidef reference" href="#fn-iextend">iextend(lst, iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Just like <a class="mochiref reference" href="#fn-list">list(iterable)</a>, except it pushes results on <tt class="docutils literal"><span class="pre">lst</span></tt>
|
||||
rather than creating a new one.</blockquote>
|
||||
<p>
|
||||
<a name="fn-ifilter"></a>
|
||||
<a class="mochidef reference" href="#fn-ifilter">ifilter(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">ifilter(pred,</span> <span class="pre">seq)</span></tt> --> elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-ifilterfalse"></a>
|
||||
<a class="mochidef reference" href="#fn-ifilterfalse">ifilterfalse(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">ifilterfalse(pred,</span> <span class="pre">seq)</span></tt> --> elements of seq where <tt class="docutils literal"><span class="pre">pred(elem)</span></tt> is</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">false</span></tt></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-imap"></a>
|
||||
<a class="mochidef reference" href="#fn-imap">imap(fun, p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">imap(fun,</span> <span class="pre">p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> fun(p0, q0, ...), fun(p1, q1, ...), ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-islice"></a>
|
||||
<a class="mochidef reference" href="#fn-islice">islice(seq, [start,] stop[, step])</a>:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">islice(seq,</span> <span class="pre">[start,]</span> <span class="pre">stop[,</span> <span class="pre">step])</span></tt> --> elements from</dt>
|
||||
<dd>seq[start:stop:step] (in Python slice syntax)</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-iter"></a>
|
||||
<a class="mochidef reference" href="#fn-iter">iter(iterable[, sentinel])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Convert the given argument to an iterator (object implementing
|
||||
<tt class="docutils literal"><span class="pre">.next()</span></tt>).</p>
|
||||
<ol class="arabic simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator (implements <tt class="docutils literal"><span class="pre">.next()</span></tt>), then it will
|
||||
be returned as-is.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">iterable</span></tt> is an iterator factory (implements <tt class="docutils literal"><span class="pre">.iter()</span></tt>), then
|
||||
the result of <tt class="docutils literal"><span class="pre">iterable.iter()</span></tt> will be returned.</li>
|
||||
<li>Otherwise, the iterator factory <a class="mochiref reference" href="Base.html#fn-adapterregistry">MochiKit.Base.AdapterRegistry</a>
|
||||
is used to find a match.</li>
|
||||
<li>If no factory is found, it will throw <tt class="docutils literal"><span class="pre">TypeError</span></tt></li>
|
||||
</ol>
|
||||
<p>Built-in iterator factories are present for Array-like objects, and
|
||||
objects that implement the <tt class="docutils literal"><span class="pre">iterateNext</span></tt> protocol (e.g. the result of
|
||||
Mozilla's <tt class="docutils literal"><span class="pre">document.evaluate</span></tt>).</p>
|
||||
<p>When used directly, using an iterator should look like this:</p>
|
||||
<pre class="literal-block">
|
||||
var it = iter(iterable);
|
||||
try {
|
||||
while (var o = it.next()) {
|
||||
// use o
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
// pass
|
||||
}
|
||||
</pre>
|
||||
<p>This is ugly, so you should use the higher order functions to work
|
||||
with iterators whenever possible.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-izip"></a>
|
||||
<a class="mochidef reference" href="#fn-izip">izip(p, q[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">izip(p,</span> <span class="pre">q,</span> <span class="pre">...)</span></tt> --> [p0, q0, ...], [p1, q1, ...], ...</blockquote>
|
||||
<p>
|
||||
<a name="fn-list"></a>
|
||||
<a class="mochidef reference" href="#fn-list">list(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Convert <tt class="docutils literal"><span class="pre">iterable</span></tt> to a new <tt class="docutils literal"><span class="pre">Array</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-next"></a>
|
||||
<a class="mochidef reference" href="#fn-next">next(iterator)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">iterator.next()</span></tt></blockquote>
|
||||
<p>
|
||||
<a name="fn-range"></a>
|
||||
<a class="mochidef reference" href="#fn-range">range([start,] stop[, step])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Return an iterator containing an arithmetic progression of integers.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">range(i,</span> <span class="pre">j)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([i, i + 1, i + 2, ..., j - 1])</a></p>
|
||||
<p><tt class="docutils literal"><span class="pre">start</span></tt> (!) defaults to <tt class="docutils literal"><span class="pre">0</span></tt>. When <tt class="docutils literal"><span class="pre">step</span></tt> is given, it specifies the
|
||||
increment (or decrement). The end point is omitted!</p>
|
||||
<p>For example, <tt class="docutils literal"><span class="pre">range(4)</span></tt> returns <a class="mochiref reference" href="#fn-iter">iter([0, 1, 2, 3])</a>.
|
||||
This iterates over exactly the valid indexes for an array of 4 elements.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-reduce"></a>
|
||||
<a class="mochidef reference" href="#fn-reduce">reduce(fn, iterable[, initial])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Apply <tt class="docutils literal"><span class="pre">fn(a,</span> <span class="pre">b)</span></tt> cumulatively to the items of an
|
||||
iterable from left to right, so as to reduce the iterable
|
||||
to a single value.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(function (a, b) { return x + y; }, [1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
<p>calculates:</p>
|
||||
<pre class="literal-block">
|
||||
((((1 + 2) + 3) + 4) + 5).
|
||||
</pre>
|
||||
<p>If initial is given, it is placed before the items of the sequence
|
||||
in the calculation, and serves as a default when the sequence is
|
||||
empty.</p>
|
||||
<p>Note that the above example could be written more clearly as:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(operator.add, [1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
<p>Or even simpler:</p>
|
||||
<pre class="literal-block">
|
||||
sum([1, 2, 3, 4, 5])
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-registeriteratorfactory"></a>
|
||||
<a class="mochidef reference" href="#fn-registeriteratorfactory">registerIteratorFactory(name, check, iterfactory[, override])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Register an iterator factory for use with the iter function.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">check</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">a</span></tt> can be
|
||||
converted into an iterator with <tt class="docutils literal"><span class="pre">iterfactory</span></tt>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is a <tt class="docutils literal"><span class="pre">function(a)</span></tt> that returns an object with a
|
||||
<tt class="docutils literal"><span class="pre">.next()</span></tt> method that returns the next value in the sequence.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">iterfactory</span></tt> is guaranteed to only be called if <tt class="docutils literal"><span class="pre">check(a)</span></tt>
|
||||
returns a true value.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">override</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then it will be made the
|
||||
highest precedence iterator factory. Otherwise, the lowest.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-repeat"></a>
|
||||
<a class="mochidef reference" href="#fn-repeat">repeat(elem[, n])</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">repeat(elem,</span> <span class="pre">[,n])</span></tt> --> elem, elem, elem, ... endlessly or up to n times</blockquote>
|
||||
<p>
|
||||
<a name="fn-reversed"></a>
|
||||
<a class="mochidef reference" href="#fn-reversed">reversed(iterable)</a>:</p>
|
||||
<blockquote>
|
||||
Return a reversed array from iterable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-some"></a>
|
||||
<a class="mochidef reference" href="#fn-some">some(iterable, func)</a>:</p>
|
||||
<blockquote>
|
||||
Return <tt class="docutils literal"><span class="pre">true</span></tt> if <tt class="docutils literal"><span class="pre">func(item)</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt> for at least one item in
|
||||
<tt class="docutils literal"><span class="pre">iterable</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-sorted"></a>
|
||||
<a class="mochidef reference" href="#fn-sorted">sorted(iterable[, cmp])</a>:</p>
|
||||
<blockquote>
|
||||
Return a sorted array from iterable.</blockquote>
|
||||
<p>
|
||||
<a name="fn-sum"></a>
|
||||
<a class="mochidef reference" href="#fn-sum">sum(iterable, start=0)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns the sum of a sequence of numbers plus the value
|
||||
of parameter <tt class="docutils literal"><span class="pre">start</span></tt> (with a default of 0). When the sequence is
|
||||
empty, returns start.</p>
|
||||
<p>Equivalent to:</p>
|
||||
<pre class="literal-block">
|
||||
reduce(operator.add, iterable, start);
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-takewhile"></a>
|
||||
<a class="mochidef reference" href="#fn-takewhile">takewhile(pred, seq)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">takewhile(pred,</span> <span class="pre">seq)</span></tt> --> seq[0], seq[1], ... until pred(seq[n]) fails</blockquote>
|
||||
<p>
|
||||
<a name="fn-tee"></a>
|
||||
<a class="mochidef reference" href="#fn-tee">tee(iterable, n=2)</a>:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">tee(it,</span> <span class="pre">n=2)</span></tt> --> [it1, it2, it3, ... itn] splits one iterator into n</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id4" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id4">[1]</a></td><td>The iteration protocol is described in
|
||||
PEP 234 - Iterators: <a class="reference" href="http://www.python.org/peps/pep-0234.html">http://www.python.org/peps/pep-0234.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id5" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id5">[2]</a></td><td>Python's itertools
|
||||
module: <a class="reference" href="http://docs.python.org/lib/module-itertools.html">http://docs.python.org/lib/module-itertools.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id3" name="id6">[3]</a></td><td>Iteration in JavaScript: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,310 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Logging - we're all tired of alert()</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Logging - we're all tired of alert()</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
log("INFO messages are so boring");
|
||||
logDebug("DEBUG messages are even worse");
|
||||
log("good thing I can pass", objects, "conveniently");
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Logging steals some ideas from Python's logging module <a class="footnote-reference" href="#id6" id="id1" name="id1">[1]</a>, but
|
||||
completely forgot about the Java <a class="footnote-reference" href="#id7" id="id2" name="id2">[2]</a> inspiration. This is a KISS module for
|
||||
logging that provides enough flexibility to do just about anything via
|
||||
listeners, but without all the cruft.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="native-console-logging" name="native-console-logging">Native Console Logging</a></h2>
|
||||
<p>As of MochiKit 1.3, the default logger will log all messages to your browser's
|
||||
native console. This is currently supported in Safari, Opera 9, and Firefox
|
||||
when the <a class="reference" href="http://www.joehewitt.com/software/firebug/">FireBug</a> extension is installed.</p>
|
||||
<p>To disable this behavior:</p>
|
||||
<pre class="literal-block">
|
||||
MochiKit.Logging.logger.useNativeLogging = false;
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="bookmarklet-based-debugging" name="bookmarklet-based-debugging">Bookmarklet Based Debugging</a></h2>
|
||||
<p>JavaScript is at a serious disadvantage without a standard console for
|
||||
"print" statements. Everything else has one. The closest thing that
|
||||
you get in a browser environment is the <tt class="docutils literal"><span class="pre">alert</span></tt> function, which is
|
||||
absolutely evil.</p>
|
||||
<p>This leaves you with one reasonable solution: do your logging in the page
|
||||
somehow. The problem here is that you don't want to clutter the page with
|
||||
debugging tools. The solution to that problem is what we call BBD, or
|
||||
Bookmarklet Based Debugging <a class="footnote-reference" href="#id8" id="id4" name="id4">[3]</a>.</p>
|
||||
<p>Simply create a bookmarklet for <a class="reference" href="javascript:MochiKit.Logging.logger.debuggingBookmarklet()">javascript:MochiKit.Logging.logger.debuggingBookmarklet()</a>,
|
||||
and whack it whenever you want to see what's in the logger. Of course, this
|
||||
means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet,
|
||||
don't worry.</p>
|
||||
<p>Currently this is an ugly <tt class="docutils literal"><span class="pre">alert</span></tt>, but we'll have something spiffy
|
||||
Real Soon Now, and when we do, you only have to upgrade MochiKit.Logging,
|
||||
not your bookmarklet!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-logmessage"></a>
|
||||
<a class="mochidef reference" href="#fn-logmessage">LogMessage(num, level, info)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
|
||||
<dd>Identifier for the log message</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
|
||||
<dd>Level of the log message (<tt class="docutils literal"><span class="pre">"INFO"</span></tt>, <tt class="docutils literal"><span class="pre">"WARN"</span></tt>, <tt class="docutils literal"><span class="pre">"DEBUG"</span></tt>,
|
||||
etc.)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
|
||||
<dd>All other arguments passed to log function as an <tt class="docutils literal"><span class="pre">Array</span></tt></dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">timestamp</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">Date</span></tt> object timestamping the log message</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger"></a>
|
||||
<a class="mochidef reference" href="#fn-logger">Logger([maxSize])</a>:</p>
|
||||
<blockquote>
|
||||
<p>A basic logger object that has a buffer of recent messages
|
||||
plus a listener dispatch mechanism for "real-time" logging
|
||||
of important messages.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">maxSize</span></tt> is the maximum number of entries in the log.
|
||||
If <tt class="docutils literal"><span class="pre">maxSize</span> <span class="pre">>=</span> <span class="pre">0</span></tt>, then the log will not buffer more than that
|
||||
many messages. So if you don't like logging at all, be sure to
|
||||
pass <tt class="docutils literal"><span class="pre">0</span></tt>.</p>
|
||||
<p>There is a default logger available named "logger", and several
|
||||
of its methods are also global functions:</p>
|
||||
<blockquote>
|
||||
<tt class="docutils literal"><span class="pre">logger.log</span></tt> -> <tt class="docutils literal"><span class="pre">log</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.debug</span></tt> -> <tt class="docutils literal"><span class="pre">logDebug</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.warning</span></tt> -> <tt class="docutils literal"><span class="pre">logWarning</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.error</span></tt> -> <tt class="docutils literal"><span class="pre">logError</span></tt>
|
||||
<tt class="docutils literal"><span class="pre">logger.fatal</span></tt> -> <tt class="docutils literal"><span class="pre">logFatal</span></tt></blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.addlistener"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener(ident, filter, listener)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Add a listener for log messages.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">ident</span></tt> is a unique identifier that may be used to remove the listener
|
||||
later on.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">filter</span></tt> can be one of the following:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">null</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called for every log message
|
||||
received.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">string</span></tt>:</dt>
|
||||
<dd><a class="mochiref reference" href="#fn-loglevelatleast">logLevelAtLeast(filter)</a> will be used as the function
|
||||
(see below).</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">function</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">filter(msg)</span></tt> will be called for every msg, if it returns
|
||||
true then <tt class="docutils literal"><span class="pre">listener(msg)</span></tt> will be called.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<p><tt class="docutils literal"><span class="pre">listener</span></tt> is a function that takes one argument, a log message. A log
|
||||
message is an object (<a class="mochiref reference" href="#fn-logmessage">LogMessage</a> instance) that has at least these
|
||||
properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">num</span></tt>:</dt>
|
||||
<dd>A counter that uniquely identifies a log message (per-logger)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">level</span></tt>:</dt>
|
||||
<dd>A string or number representing the log level. If string, you
|
||||
may want to use <tt class="docutils literal"><span class="pre">LogLevel[level]</span></tt> for comparison.</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">info</span></tt>:</dt>
|
||||
<dd>An Array of objects passed as additional arguments to the <tt class="docutils literal"><span class="pre">log</span></tt>
|
||||
function.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.baselog"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.baselog">Logger.prototype.baseLog(level, message[, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p>The base functionality behind all of the log functions.
|
||||
The first argument is the log level as a string or number,
|
||||
and all other arguments are used as the info list.</p>
|
||||
<p>This function is available partially applied as:</p>
|
||||
<blockquote>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="61%" />
|
||||
<col width="39%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>Logger.debug</td>
|
||||
<td>'DEBUG'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.log</td>
|
||||
<td>'INFO'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.error</td>
|
||||
<td>'ERROR'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.fatal</td>
|
||||
<td>'FATAL'</td>
|
||||
</tr>
|
||||
<tr><td>Logger.warning</td>
|
||||
<td>'WARNING'</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>For the default logger, these are also available as global functions,
|
||||
see the <a class="mochiref reference" href="#fn-logger">Logger</a> constructor documentation for more info.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.clear"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.clear">Logger.prototype.clear()</a>:</p>
|
||||
<blockquote>
|
||||
Clear all messages from the message buffer.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.debuggingbookmarklet"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.debuggingbookmarklet">Logger.prototype.debuggingBookmarklet()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Display the contents of the logger in a useful way for browsers.</p>
|
||||
<p>Currently, if <a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> is loaded, then a pop-up
|
||||
<a class="mochiref reference" href="LoggingPane.html#fn-loggingpane">MochiKit.LoggingPane.LoggingPane</a> will be used. Otherwise,
|
||||
it will be an alert with <a class="mochiref reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText()</a>.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.dispatchlisteners"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.dispatchlisteners">Logger.prototype.dispatchListeners(msg)</a>:</p>
|
||||
<blockquote>
|
||||
Dispatch a log message to all listeners.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.getmessages"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages(howMany)</a>:</p>
|
||||
<blockquote>
|
||||
Return a list of up to <tt class="docutils literal"><span class="pre">howMany</span></tt> messages from the message buffer.</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.getmessagetext"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.getmessagetext">Logger.prototype.getMessageText(howMany)</a>:</p>
|
||||
<blockquote>
|
||||
<p>Get a string representing up to the last <tt class="docutils literal"><span class="pre">howMany</span></tt> messages in the
|
||||
message buffer. The default is <tt class="docutils literal"><span class="pre">30</span></tt>.</p>
|
||||
<p>The message looks like this:</p>
|
||||
<pre class="literal-block">
|
||||
LAST {messages.length} MESSAGES:
|
||||
[{msg.num}] {msg.level}: {m.info.join(' ')}
|
||||
[{msg.num}] {msg.level}: {m.info.join(' ')}
|
||||
...
|
||||
</pre>
|
||||
<p>If you want some other format, use
|
||||
<a class="mochiref reference" href="#fn-logger.prototype.getmessages">Logger.prototype.getMessages</a> and do it yourself.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-logger.prototype.removelistener"></a>
|
||||
<a class="mochidef reference" href="#fn-logger.prototype.removelistener">Logger.prototype.removeListener(ident)</a>:</p>
|
||||
<blockquote>
|
||||
Remove a listener using the ident given to <a class="mochiref reference" href="#fn-logger.prototype.addlistener">Logger.prototype.addListener</a></blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-alertlistener"></a>
|
||||
<a class="mochidef reference" href="#fn-alertlistener">alertListener(msg)</a>:</p>
|
||||
<blockquote>
|
||||
Ultra-obnoxious <tt class="docutils literal"><span class="pre">alert(...)</span></tt> listener</blockquote>
|
||||
<p>
|
||||
<a name="fn-logdebug"></a>
|
||||
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log an INFO message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logdebug"></a>
|
||||
<a class="mochidef reference" href="#fn-logdebug">logDebug(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a DEBUG message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logerror"></a>
|
||||
<a class="mochidef reference" href="#fn-logerror">logError(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log an ERROR message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-logfatal"></a>
|
||||
<a class="mochidef reference" href="#fn-logfatal">logFatal(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a FATAL message to the default logger</blockquote>
|
||||
<p>
|
||||
<a name="fn-loglevelatleast"></a>
|
||||
<a class="mochidef reference" href="#fn-loglevelatleast">logLevelAtLeast(minLevel)</a>:</p>
|
||||
<blockquote>
|
||||
Return a function that will match log messages whose level
|
||||
is at least minLevel</blockquote>
|
||||
<p>
|
||||
<a name="fn-logwarning"></a>
|
||||
<a class="mochidef reference" href="#fn-logwarning">logWarning(message[, info[, ...]])</a>:</p>
|
||||
<blockquote>
|
||||
Log a WARNING message to the default logger</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id6" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id1" name="id6">[1]</a></td><td>Python's logging module: <a class="reference" href="http://docs.python.org/lib/module-logging.html">http://docs.python.org/lib/module-logging.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id7" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id2" name="id7">[2]</a></td><td>PEP 282, where they admit all of the Java influence: <a class="reference" href="http://www.python.org/peps/pep-0282.html">http://www.python.org/peps/pep-0282.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id8" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a class="fn-backref" href="#id4" name="id8">[3]</a></td><td>Original Bookmarklet Based Debugging blather: <a class="reference" href="http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/">http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,121 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.LoggingPane - Interactive MochiKit.Logging pane</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// open a pop-up window
|
||||
createLoggingPane()
|
||||
// use a div at the bottom of the document
|
||||
createLoggingPane(true);
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Logging does not have any browser dependencies and is completely
|
||||
unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane
|
||||
for your <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> output that can be used as a pop-up or
|
||||
inline.</p>
|
||||
<p>It also allows for regex and level filtering! MochiKit.LoggingPane is used
|
||||
as the default <a class="mochiref reference" href="Logging.html#fn-debuggingbookmarklet">MochiKit.Logging.debuggingBookmarklet()</a> if it is
|
||||
loaded.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="constructors" name="constructors">Constructors</a></h2>
|
||||
<p>
|
||||
<a name="fn-loggingpane"></a>
|
||||
<a class="mochidef reference" href="#fn-loggingpane">LoggingPane(inline=false, logger=MochiKit.Logging.logger)</a>:</p>
|
||||
<blockquote>
|
||||
<p>A listener for a <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> logger with an interactive
|
||||
DOM representation.</p>
|
||||
<p>If <tt class="docutils literal"><span class="pre">inline</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, then the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> will be a <tt class="docutils literal"><span class="pre">DIV</span></tt>
|
||||
at the bottom of the document. Otherwise, it will be in a pop-up
|
||||
window with a name based on the calling page's URL. If there is an
|
||||
element in the document with an id of <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt>,
|
||||
it will be used instead of appending a new <tt class="docutils literal"><span class="pre">DIV</span></tt> to the body.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">logger</span></tt> is the reference to the <a class="mochiref reference" href="Logging.html#fn-logger">MochiKit.Logging.Logger</a> to
|
||||
listen to. If not specified, the global default logger is used.</p>
|
||||
<p>Properties:</p>
|
||||
<blockquote>
|
||||
<dl class="docutils">
|
||||
<dt><tt class="docutils literal"><span class="pre">win</span></tt>:</dt>
|
||||
<dd>Reference to the pop-up window (<tt class="docutils literal"><span class="pre">undefined</span></tt> if <tt class="docutils literal"><span class="pre">inline</span></tt>)</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">inline</span></tt>:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">true</span></tt> if the <tt class="docutils literal"><span class="pre">LoggingPane</span></tt> is inline</dd>
|
||||
<dt><tt class="docutils literal"><span class="pre">colorTable</span></tt>:</dt>
|
||||
<dd><p class="first">An object with property->value mappings for each log level
|
||||
and its color. May also be mutated on <tt class="docutils literal"><span class="pre">LoggingPane.prototype</span></tt>
|
||||
to affect all instances. For example:</p>
|
||||
<pre class="last literal-block">
|
||||
MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
|
||||
DEBUG: "green",
|
||||
INFO: "black",
|
||||
WARNING: "blue",
|
||||
ERROR: "red",
|
||||
FATAL: "darkred"
|
||||
};
|
||||
</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-loggingpane.prototype.closepane"></a>
|
||||
<a class="mochidef reference" href="#fn-loggingpane.prototype.closepane">LoggingPane.prototype.closePane()</a>:</p>
|
||||
<blockquote>
|
||||
Close the <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> (close the child window, or
|
||||
remove the <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> <tt class="docutils literal"><span class="pre">DIV</span></tt> from the document).</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-createloggingpane"></a>
|
||||
<a class="mochidef reference" href="#fn-createloggingpane">createLoggingPane(inline=false)</a>:</p>
|
||||
<blockquote>
|
||||
Create or return an existing <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> for this document
|
||||
with the given inline setting. This is preferred over using
|
||||
<a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a> directly, as only one <a class="mochiref reference" href="#fn-loggingpane">LoggingPane</a>
|
||||
should be present in a given document.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,331 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Signal - Simple universal event handling</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Signal - Simple universal event handling</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<p>Signal for DOM events:</p>
|
||||
<pre class="literal-block">
|
||||
// DOM events are also signals. Connect freely! The functions will be
|
||||
// called with the custom event as a parameter.
|
||||
|
||||
// calls myClicked.apply(getElement('myID'), event)
|
||||
connect('myID', 'onclick', myClicked);
|
||||
|
||||
// calls wasClicked.apply(myObject, event)
|
||||
connect('myID', 'onclick', myObject, wasClicked);
|
||||
|
||||
// calls myObject.wasClicked(event)
|
||||
connect('myID', 'onclick', myObject, 'wasClicked');
|
||||
|
||||
// the event is normalized, no more e = e || window.event!
|
||||
myObject.wasClicked = function(e) {
|
||||
var crossBrowserCoordinates = e.mouse().page;
|
||||
// e.mouse().page is a MochiKit.DOM.Coordinates object
|
||||
}
|
||||
</pre>
|
||||
<p>Signal for non-DOM events:</p>
|
||||
<pre class="literal-block">
|
||||
// otherObject.gotFlash() will be called when 'flash' signalled.
|
||||
connect(myObject, 'flash', otherObject, 'gotFlash');
|
||||
|
||||
// gotBang.apply(otherObject) will be called when 'bang' signalled.
|
||||
// You can access otherObject from within gotBang as 'this'.
|
||||
connect(myObject, 'bang', otherObject, gotBang);
|
||||
|
||||
// myFunc.apply(myObject) will be called when 'flash' signalled.
|
||||
// You can access myObject from within myFunc as 'this'.
|
||||
var ident = connect(myObject, 'flash', myFunc);
|
||||
|
||||
// You may disconnect with the return value from connect
|
||||
disconnect(ident);
|
||||
|
||||
// Signal can take parameters. These will be passed along to the connected
|
||||
// functions.
|
||||
signal(myObject, 'flash');
|
||||
signal(myObject, 'bang', 'BANG!');
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>Event handling was never so easy!</p>
|
||||
<p>This module takes care of all the hard work—figuring out which event
|
||||
model to use, trying to retrieve the event object, and handling your own
|
||||
internal events, as well as cleanup when the page is unloaded to clean up IE's
|
||||
nasty memory leakage.</p>
|
||||
<p>This event system is largely based on Qt's signal/slot system. Read more on
|
||||
how that is handled and also how it is used in model/view programming at:
|
||||
<a class="reference" href="http://doc.trolltech.com/">http://doc.trolltech.com/</a></p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="using-signal-for-dom-events" name="using-signal-for-dom-events">Using Signal for DOM Events</a></h2>
|
||||
<p>When using MochiKit.Signal, do not use the browser's native event API. That
|
||||
means, no <tt class="docutils literal"><span class="pre">onclick="blah"</span></tt>, no <tt class="docutils literal"><span class="pre">elem.addEventListener(...)</span></tt>, and certainly
|
||||
no <tt class="docutils literal"><span class="pre">elem.attachEvent(...)</span></tt>. This also means that
|
||||
<a class="mochiref reference" href="DOM.html#fn-addtocallstack">MochiKit.DOM.addToCallStack</a> and
|
||||
<a class="mochiref reference" href="DOM.html#fn-addloadevent">MochiKit.DOM.addLoadEvent</a> should not be used in combination with
|
||||
this module.</p>
|
||||
<p>Signals for DOM objects are named with the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix, e.g.:
|
||||
<tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>, etc.</p>
|
||||
<p>When the signal fires, your slot will be called with one parameter, the custom
|
||||
event object.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="custom-event-objects-for-dom-events" name="custom-event-objects-for-dom-events">Custom Event Objects for DOM events</a></h2>
|
||||
<p>Signals triggered by DOM events are called with a custom event object as a
|
||||
parameter. The custom event object presents a consistent view of the event
|
||||
across all supported platforms and browsers, and provides many conveniences
|
||||
not available even in a correct W3C implementation.</p>
|
||||
<p>See the <a class="reference" href="#dom-custom-event-object-reference">DOM Custom Event Object Reference</a> for a detailed API description
|
||||
of this object.</p>
|
||||
<p>If you find that you're accessing the native event for any reason, create a
|
||||
<a class="reference" href="http://trac.mochikit.com/newticket">new ticket</a> and we'll look into normalizing the behavior you're looking for.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="memory-usage" name="memory-usage">Memory Usage</a></h2>
|
||||
<p>Any object that has connected slots (via <a class="mochiref reference" href="#fn-connect">connect()</a>) is referenced
|
||||
by the Signal mechanism until it is disconnected via <a class="mochiref reference" href="#fn-disconnect">disconnect()</a>
|
||||
or <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>.</p>
|
||||
<p>Signal does not leak. It registers an <tt class="docutils literal"><span class="pre">'onunload'</span></tt> event that disconnects all
|
||||
objects on the page when the browser leaves the page. However, memory usage
|
||||
will grow during the page view for every connection made until it is
|
||||
disconnected. Even if the DOM object is removed from the document, it
|
||||
will still be referenced by Signal until it is explicitly disconnected.</p>
|
||||
<p>In order to conserve memory during the page view, <a class="mochiref reference" href="#fn-disconnectall">disconnectAll()</a>
|
||||
any DOM elements that are about to be removed from the document.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="using-signal-for-non-dom-objects" name="using-signal-for-non-dom-objects">Using Signal for non-DOM objects</a></h2>
|
||||
<p>Signals are triggered with the <a class="mochiref reference" href="#fn-signal">signal(src, 'signal', ...)</a>
|
||||
function. Additional parameters passed to this are passed onto the
|
||||
connected slots. Explicit signals are not required for DOM events.</p>
|
||||
<p>Slots that are connected to a signal are called in the following manner
|
||||
when that signal is signalled:</p>
|
||||
<ul class="simple">
|
||||
<li>If the slot was a single function, then it is called with <tt class="docutils literal"><span class="pre">this</span></tt> set
|
||||
to the object originating the signal with whatever parameters it was
|
||||
signalled with.</li>
|
||||
<li>If the slot was an object and a function, then it is called with
|
||||
<tt class="docutils literal"><span class="pre">this</span></tt> set to the object, and with whatever parameters it was
|
||||
signalled with.</li>
|
||||
<li>If the slot was an object and a string, then <tt class="docutils literal"><span class="pre">object[string]</span></tt> is
|
||||
called with the parameters to the signal.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="signal-api-reference" name="signal-api-reference">Signal API Reference</a></h2>
|
||||
<p>
|
||||
<a name="fn-connect"></a>
|
||||
<a class="mochidef reference" href="#fn-connect">connect(src, signal, dest[, func])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Connects a signal to a slot, and return a unique identifier that can be
|
||||
used to disconnect that signal.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">src</span></tt> is the object that has the signal. You may pass in a string, in
|
||||
which case, it is interpreted as an id for an HTML element.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">signal</span></tt> is a string that represents a signal name. If 'src' is an HTML
|
||||
Element, <tt class="docutils literal"><span class="pre">window</span></tt>, or the <tt class="docutils literal"><span class="pre">document</span></tt>, then it can be one of the
|
||||
'on-XYZ' events. You must include the 'on' prefix, and it must be all
|
||||
lower-case.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">dest</span></tt> and <tt class="docutils literal"><span class="pre">func</span></tt> describe the slot, or the action to take when the
|
||||
signal is triggered.</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a string, then
|
||||
<tt class="docutils literal"><span class="pre">dest[func].apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal
|
||||
is signalled.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">dest</span></tt> is an object and <tt class="docutils literal"><span class="pre">func</span></tt> is a function, then
|
||||
<tt class="docutils literal"><span class="pre">func.apply(dest,</span> <span class="pre">...)</span></tt> will be called when the signal is
|
||||
signalled.</li>
|
||||
<li>If <tt class="docutils literal"><span class="pre">func</span></tt> is undefined and <tt class="docutils literal"><span class="pre">dest</span></tt> is a function, then
|
||||
<tt class="docutils literal"><span class="pre">func.apply(src,</span> <span class="pre">...)</span></tt> will be called when the signal is
|
||||
signalled.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>No other combinations are allowed and will raise an exception.</p>
|
||||
<p>The return value can be passed to <a class="mochiref reference" href="#fn-disconnect">disconnect</a> to disconnect
|
||||
the signal.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-disconnect"></a>
|
||||
<a class="mochidef reference" href="#fn-disconnect">disconnect(ident)</a>:</p>
|
||||
<blockquote>
|
||||
To disconnect a signal, pass its ident returned by <a class="mochiref reference" href="#fn-connect">connect()</a>.
|
||||
This is similar to how the browser's <tt class="docutils literal"><span class="pre">setTimeout</span></tt> and <tt class="docutils literal"><span class="pre">clearTimeout</span></tt>
|
||||
works.</blockquote>
|
||||
<p>
|
||||
<a name="fn-disconnectall"></a>
|
||||
<a class="mochidef reference" href="#fn-disconnectall">disconnectAll(src[, signal, ...])</a>:</p>
|
||||
<blockquote>
|
||||
<p><tt class="docutils literal"><span class="pre">disconnectAll(src)</span></tt> removes all signals from src.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">disconnectAll(src,</span> <span class="pre">'onmousedown',</span> <span class="pre">'mySignal')</span></tt> will remove all
|
||||
<tt class="docutils literal"><span class="pre">'onmousedown'</span></tt> and <tt class="docutils literal"><span class="pre">'mySignal'</span></tt> signals from src.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-signal"></a>
|
||||
<a class="mochidef reference" href="#fn-signal">signal(src, signal, ...)</a>:</p>
|
||||
<blockquote>
|
||||
This will signal a signal, passing whatever additional parameters on to
|
||||
the connected slots. <tt class="docutils literal"><span class="pre">src</span></tt> and <tt class="docutils literal"><span class="pre">signal</span></tt> are the same as for
|
||||
<a class="mochiref reference" href="#fn-connect">connect()</a>.</blockquote>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2><a id="dom-custom-event-object-reference" name="dom-custom-event-object-reference">DOM Custom Event Object Reference</a></h2>
|
||||
<p>
|
||||
<a name="fn-event"></a>
|
||||
<a class="mochidef reference" href="#fn-event">event()</a>:</p>
|
||||
<blockquote>
|
||||
The native event produced by the browser. You should not need to use this.</blockquote>
|
||||
<p>
|
||||
<a name="fn-src"></a>
|
||||
<a class="mochidef reference" href="#fn-src">src()</a>:</p>
|
||||
<blockquote>
|
||||
The element that this signal is connected to.</blockquote>
|
||||
<p>
|
||||
<a name="fn-type"></a>
|
||||
<a class="mochidef reference" href="#fn-type">type()</a>:</p>
|
||||
<blockquote>
|
||||
The event type (<tt class="docutils literal"><span class="pre">'click'</span></tt>, <tt class="docutils literal"><span class="pre">'mouseover'</span></tt>, <tt class="docutils literal"><span class="pre">'keypress'</span></tt>, etc.) as a
|
||||
string. Does not include the <tt class="docutils literal"><span class="pre">'on'</span></tt> prefix.</blockquote>
|
||||
<p>
|
||||
<a name="fn-target"></a>
|
||||
<a class="mochidef reference" href="#fn-target">target()</a>:</p>
|
||||
<blockquote>
|
||||
The element that triggered the event. This may be a child of
|
||||
<a class="mochiref reference" href="#fn-src">src()</a>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-modifier"></a>
|
||||
<a class="mochidef reference" href="#fn-modifier">modifier()</a>:</p>
|
||||
<blockquote>
|
||||
Returns <tt class="docutils literal"><span class="pre">{shift,</span> <span class="pre">ctrl,</span> <span class="pre">meta,</span> <span class="pre">alt,</span> <span class="pre">any}</span></tt>, where each property is <tt class="docutils literal"><span class="pre">true</span></tt>
|
||||
if its respective modifier key was pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise. <tt class="docutils literal"><span class="pre">any</span></tt>
|
||||
is <tt class="docutils literal"><span class="pre">true</span></tt> if any modifier is pressed, <tt class="docutils literal"><span class="pre">false</span></tt> otherwise.</blockquote>
|
||||
<p>
|
||||
<a name="fn-stoppropagation"></a>
|
||||
<a class="mochidef reference" href="#fn-stoppropagation">stopPropagation()</a>:</p>
|
||||
<blockquote>
|
||||
Works like W3C's <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-preventdefault"></a>
|
||||
<a class="mochidef reference" href="#fn-preventdefault">preventDefault()</a>:</p>
|
||||
<blockquote>
|
||||
Works like W3C's <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-stop"></a>
|
||||
<a class="mochidef reference" href="#fn-stop">stop()</a>:</p>
|
||||
<blockquote>
|
||||
Shortcut that calls <tt class="docutils literal"><span class="pre">stopPropagation()</span></tt> and <tt class="docutils literal"><span class="pre">preventDefault()</span></tt>.</blockquote>
|
||||
<p>
|
||||
<a name="fn-key"></a>
|
||||
<a class="mochidef reference" href="#fn-key">key()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Returns <tt class="docutils literal"><span class="pre">{code,</span> <span class="pre">string}</span></tt>.</p>
|
||||
<p>Use <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> handlers to detect control
|
||||
characters such as <tt class="docutils literal"><span class="pre">'KEY_F1'</span></tt>. Use the <tt class="docutils literal"><span class="pre">'onkeypressed'</span></tt> handler to
|
||||
detect "printable" characters, such as <tt class="docutils literal"><span class="pre">'é'</span></tt>.</p>
|
||||
<p>When a user presses F1, in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt> this method
|
||||
returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">122,</span> <span class="pre">string:</span> <span class="pre">'KEY_F1'}</span></tt>. In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns
|
||||
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">0,</span> <span class="pre">string:</span> <span class="pre">''}</span></tt>.</p>
|
||||
<p>If a user presses Shift+2 on a US keyboard, this method returns
|
||||
<tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">50,</span> <span class="pre">string:</span> <span class="pre">'KEY_2'}</span></tt> in <tt class="docutils literal"><span class="pre">'onkeydown'</span></tt> and <tt class="docutils literal"><span class="pre">'onkeyup'</span></tt>.
|
||||
In <tt class="docutils literal"><span class="pre">'onkeypress'</span></tt>, it returns <tt class="docutils literal"><span class="pre">{code:</span> <span class="pre">64,</span> <span class="pre">string:</span> <span class="pre">'@'}</span></tt>.</p>
|
||||
<p>See <tt class="docutils literal"><span class="pre">_specialKeys</span></tt> in the source code for a comprehensive list of
|
||||
control characters.</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-mouse"></a>
|
||||
<a class="mochidef reference" href="#fn-mouse">mouse()</a>:</p>
|
||||
<blockquote>
|
||||
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouse*'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>, and
|
||||
<tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">page</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
|
||||
represents the cursor position relative to the HTML document.
|
||||
Equivalent to <tt class="docutils literal"><span class="pre">pageX</span></tt> and <tt class="docutils literal"><span class="pre">pageY</span></tt> in Safari, Mozilla, and
|
||||
Opera.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">client</span></tt> is a <a class="mochiref reference" href="DOM.html#fn-coordinates">MochiKit.DOM.Coordinates</a> object that
|
||||
represents the cursor position relative to the visible portion of
|
||||
the HTML document. Equivalent to <tt class="docutils literal"><span class="pre">clientX</span></tt> and <tt class="docutils literal"><span class="pre">clientY</span></tt> on
|
||||
all browsers.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Properties for <tt class="docutils literal"><span class="pre">'onmouseup'</span></tt>, <tt class="docutils literal"><span class="pre">'onmousedown'</span></tt>, <tt class="docutils literal"><span class="pre">'onclick'</span></tt>, and
|
||||
<tt class="docutils literal"><span class="pre">'ondblclick'</span></tt>:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">mouse().button</span></tt> returns <tt class="docutils literal"><span class="pre">{left,</span> <span class="pre">right,</span> <span class="pre">middle}</span></tt> where each
|
||||
property is <tt class="docutils literal"><span class="pre">true</span></tt> if the mouse button was pressed, <tt class="docutils literal"><span class="pre">false</span></tt>
|
||||
otherwise.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Known browser bugs:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">Current versions of Safari won't signal <tt class="docutils literal"><span class="pre">'ondblclick'</span></tt> when
|
||||
attached via <tt class="docutils literal"><span class="pre">connect()</span></tt> (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7790">Safari Bug 7790</a>).</p>
|
||||
</li>
|
||||
<li><p class="first">Mac browsers don't report right-click consistently. Firefox
|
||||
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().ctrl</span></tt> to true, Opera
|
||||
signals the slot and sets <tt class="docutils literal"><span class="pre">modifier().meta</span></tt> to <tt class="docutils literal"><span class="pre">true</span></tt>, and
|
||||
Safari doesn't signal the slot at all (<a class="reference" href="http://bugzilla.opendarwin.org/show_bug.cgi?id=6595">Safari Bug 6595</a>).</p>
|
||||
<p>To find a right-click in Safari, Firefox, and IE, you can connect
|
||||
an element to <tt class="docutils literal"><span class="pre">'oncontextmenu'</span></tt>. This doesn't work in Opera.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<p>
|
||||
<a name="fn-relatedtarget"></a>
|
||||
<a class="mochidef reference" href="#fn-relatedtarget">relatedTarget()</a>:</p>
|
||||
<blockquote>
|
||||
Returns the document element that the mouse has moved to. This is
|
||||
generated for <tt class="docutils literal"><span class="pre">'onmouseover'</span></tt> and <tt class="docutils literal"><span class="pre">'onmouseout'</span></tt> events.</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Jonathan Gardner <<a class="reference" href="mailto:jgardner@jonathangardner.net">jgardner@jonathangardner.net</a>></li>
|
||||
<li>Beau Hartshorne <<a class="reference" href="mailto:beau@hartshornesoftware.com">beau@hartshornesoftware.com</a>></li>
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2006 Jonathan Gardner <<a class="reference" href="mailto:jgardner@jonathangardner.net">jgardner@jonathangardner.net</a>>, Beau
|
||||
Hartshorne <<a class="reference" href="mailto:beau@hartshornesoftware.com">beau@hartshornesoftware.com</a>>, and Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>.
|
||||
This program is dual-licensed free software; you can redistribute it and/or
|
||||
modify it under the terms of the <a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,264 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title></title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<p>2006-04-29 v1.3.1 (bug fix release)</p>
|
||||
<ul class="simple">
|
||||
<li>Fix sendXMLHttpRequest sendContent regression</li>
|
||||
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
|
||||
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
|
||||
</ul>
|
||||
<p>2006-04-26 v1.3 "warp zone"</p>
|
||||
<ul class="simple">
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
|
||||
<li>New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method</li>
|
||||
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array</li>
|
||||
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
|
||||
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.</li>
|
||||
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").</li>
|
||||
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.</li>
|
||||
<li>Native Console Logging for the default MochiKit.Logging logger</li>
|
||||
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
|
||||
<li>New MochiKit.Signal example: draggable</li>
|
||||
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly</li>
|
||||
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
|
||||
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.</li>
|
||||
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size</li>
|
||||
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.</li>
|
||||
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.</li>
|
||||
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
|
||||
<li>MochiKit.Base.isNull no longer matches undefined</li>
|
||||
<li>example doctypes changed to HTML4</li>
|
||||
<li>isDateLike no longer throws error on null</li>
|
||||
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
|
||||
<li>updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth</li>
|
||||
<li>formContents now works with FORM tags that have a name attribute</li>
|
||||
<li>Documentation now uses MochiKit to generate a function index</li>
|
||||
</ul>
|
||||
<p>2006-01-26 v1.2 "the ocho"</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
|
||||
<li>Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.</li>
|
||||
<li>Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.</li>
|
||||
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].</li>
|
||||
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility</li>
|
||||
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
|
||||
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document</li>
|
||||
<li>MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino</li>
|
||||
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
|
||||
currently in the document instead of always creating one.</li>
|
||||
<li>MochiKit.Base now has operator.mul</li>
|
||||
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute</li>
|
||||
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
|
||||
<li>MochiKit.DOM.setNodeAttribute should work now</li>
|
||||
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string</li>
|
||||
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties</li>
|
||||
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
|
||||
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
|
||||
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
|
||||
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
|
||||
<li>Added new MochiKit.DOM documentation on element visibility</li>
|
||||
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
|
||||
</ul>
|
||||
<p>2005-11-14 v1.1</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed a bug in numberFormatter with large numbers</li>
|
||||
<li>Massively overhauled documentation</li>
|
||||
<li>Fast-path for primitives in MochiKit.Base.compare</li>
|
||||
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
|
||||
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
|
||||
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET</li>
|
||||
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
|
||||
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
|
||||
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)</li>
|
||||
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)</li>
|
||||
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)</li>
|
||||
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the <em>last</em> argument, not the first when this feature
|
||||
is used.</li>
|
||||
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string</li>
|
||||
<li>Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes</li>
|
||||
<li>escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.</li>
|
||||
<li>Added DeferredLock to Async</li>
|
||||
<li>Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM</li>
|
||||
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
|
||||
<li>Fixed range() to accept a negative step</li>
|
||||
<li>New alias to MochiKit.swapDOM called removeElement</li>
|
||||
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})</li>
|
||||
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising</li>
|
||||
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)</li>
|
||||
</ul>
|
||||
<p>2005-10-24 v1.0</p>
|
||||
<ul class="simple">
|
||||
<li>New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter</li>
|
||||
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage</li>
|
||||
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool</li>
|
||||
<li>Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")</li>
|
||||
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
|
||||
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format</li>
|
||||
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
|
||||
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond</li>
|
||||
<li>Fixed infinite recusion bug when using roundClass("DIV", ...)</li>
|
||||
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly</li>
|
||||
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert</li>
|
||||
<li>Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null</li>
|
||||
</ul>
|
||||
<p>2005-10-08 v0.90</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed ISO compliance with toISODate</li>
|
||||
<li>Added missing operator.sub</li>
|
||||
<li>Placated Mozilla's strict warnings a bit</li>
|
||||
<li>Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.</li>
|
||||
<li>Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM</li>
|
||||
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.</li>
|
||||
</ul>
|
||||
<p>2005-08-12 v0.80</p>
|
||||
<ul class="simple">
|
||||
<li>Source highlighting in all examples, moved to a view-source example</li>
|
||||
<li>Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
|
||||
<li>Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).</li>
|
||||
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement</li>
|
||||
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)</li>
|
||||
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
|
||||
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
|
||||
<li>Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id</li>
|
||||
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
|
||||
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
|
||||
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM</li>
|
||||
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
|
||||
<li>Added HSV color space support to MochiKit.Visual</li>
|
||||
<li>Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly</li>
|
||||
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope</li>
|
||||
</ul>
|
||||
<p>2005-08-04 v0.70</p>
|
||||
<ul class="simple">
|
||||
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.</li>
|
||||
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests</li>
|
||||
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
|
||||
<li>Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.</li>
|
||||
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).</li>
|
||||
<li>Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString</li>
|
||||
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).</li>
|
||||
<li>Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).</li>
|
||||
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
|
||||
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!</li>
|
||||
</ul>
|
||||
<p>2005-07-29 v0.60</p>
|
||||
<ul class="simple">
|
||||
<li>Beefed up the MochiKit.DOM test suite</li>
|
||||
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before</li>
|
||||
<li>Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName</li>
|
||||
<li>Added a "packed" version in packed/lib/MochiKit/MochiKit.js</li>
|
||||
<li>Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization</li>
|
||||
<li>MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.</li>
|
||||
<li>Several minor documentation corrections</li>
|
||||
</ul>
|
||||
<p>2005-07-27 v0.50</p>
|
||||
<ul class="simple">
|
||||
<li>Initial Release</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,162 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit.Visual - visual effects</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="name" name="name">Name</a></h1>
|
||||
<p>MochiKit.Visual - visual effects</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="synopsis" name="synopsis">Synopsis</a></h1>
|
||||
<pre class="literal-block">
|
||||
// round the corners of all h1 elements
|
||||
roundClass("h1", null);
|
||||
|
||||
// round the top left corner of the element with the id "title"
|
||||
roundElement("title", {corners: "tl"});
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="description" name="description">Description</a></h1>
|
||||
<p>MochiKit.Visual provides visual effects and support functions for visuals.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="dependencies" name="dependencies">Dependencies</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a></li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a></li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a></li>
|
||||
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="overview" name="overview">Overview</a></h1>
|
||||
<p>At this time, MochiKit.Visual provides one visual effect: rounded corners
|
||||
for your HTML elements. These rounded corners are created completely
|
||||
through CSS manipulations and require no external images or style sheets.
|
||||
This implementation was adapted from <a class="reference" href="http://www.openrico.org">Rico</a>.</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="api-reference" name="api-reference">API Reference</a></h1>
|
||||
<div class="section">
|
||||
<h2><a id="functions" name="functions">Functions</a></h2>
|
||||
<p>
|
||||
<a name="fn-roundclass"></a>
|
||||
<a class="mochidef reference" href="#fn-roundclass">roundClass(tagName[, className[, options]])</a>:</p>
|
||||
<blockquote>
|
||||
Rounds all of the elements that match the <tt class="docutils literal"><span class="pre">tagName</span></tt> and <tt class="docutils literal"><span class="pre">className</span></tt>
|
||||
specifiers, using the options provided. <tt class="docutils literal"><span class="pre">tagName</span></tt> or <tt class="docutils literal"><span class="pre">className</span></tt> can
|
||||
be <tt class="docutils literal"><span class="pre">null</span></tt> to match all tags or classes. For more information about
|
||||
the options, see the <a class="mochiref reference" href="#fn-roundelement">roundElement</a> function.</blockquote>
|
||||
<p>
|
||||
<a name="fn-roundelement"></a>
|
||||
<a class="mochidef reference" href="#fn-roundelement">roundElement(element[, options])</a>:</p>
|
||||
<blockquote>
|
||||
<p>Immediately round the corners of the specified element.
|
||||
The element can be given as either a string
|
||||
with the element ID, or as an element object.</p>
|
||||
<p>The options mapping has the following defaults:</p>
|
||||
<table border="1" class="docutils">
|
||||
<colgroup>
|
||||
<col width="35%" />
|
||||
<col width="65%" />
|
||||
</colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td>corners</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"all"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>color</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"fromElement"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>bgColor</td>
|
||||
<td><tt class="docutils literal"><span class="pre">"fromParent"</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>blend</td>
|
||||
<td><tt class="docutils literal"><span class="pre">true</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>border</td>
|
||||
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
|
||||
</tr>
|
||||
<tr><td>compact</td>
|
||||
<td><tt class="docutils literal"><span class="pre">false</span></tt></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>corners:</p>
|
||||
<blockquote>
|
||||
<p>specifies which corners of the element should be rounded.
|
||||
Choices are:</p>
|
||||
<ul class="simple">
|
||||
<li>all</li>
|
||||
<li>top</li>
|
||||
<li>bottom</li>
|
||||
<li>tl (top left)</li>
|
||||
<li>bl (bottom left)</li>
|
||||
<li>tr (top right)</li>
|
||||
<li>br (bottom right)</li>
|
||||
</ul>
|
||||
<dl class="docutils">
|
||||
<dt>Example:</dt>
|
||||
<dd><tt class="docutils literal"><span class="pre">"tl</span> <span class="pre">br"</span></tt>: top-left and bottom-right corners are rounded</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
<dl class="docutils">
|
||||
<dt>blend:</dt>
|
||||
<dd>specifies whether the color and background color should be blended
|
||||
together to produce the border color.</dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<table class="docutils footnote" frame="void" id="id1" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id1">[1]</a></td><td>Application Kit Reference - NSColor: <a class="reference" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html">http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id2" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id2">[2]</a></td><td>SVG 1.0 color keywords: <a class="reference" href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">http://www.w3.org/TR/SVG/types.html#ColorKeywords</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="docutils footnote" frame="void" id="id3" rules="none">
|
||||
<colgroup><col class="label" /><col /></colgroup>
|
||||
<tbody valign="top">
|
||||
<tr><td class="label"><a name="id3">[3]</a></td><td>W3C CSS3 Color Module: <a class="reference" href="http://www.w3.org/TR/css3-color/#svg-color">http://www.w3.org/TR/css3-color/#svg-color</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="authors" name="authors">Authors</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Kevin Dangoor <<a class="reference" href="mailto:dangoor@gmail.com">dangoor@gmail.com</a>></li>
|
||||
<li>Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>></li>
|
||||
<li>Originally adapted from Rico <<a class="reference" href="http://openrico.org/">http://openrico.org/</a>> (though little remains)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
<p>Portions adapted from <a class="reference" href="http://www.openrico.org">Rico</a> are available under the terms of the
|
||||
<a class="reference" href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache License, Version 2.0</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,319 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
|
||||
<title>MochiKit Documentation Index</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../include/css/documentation.css" type="text/css" />
|
||||
<script type="text/javascript" src="../../../packed/lib/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../js/toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document">
|
||||
<div class="section">
|
||||
<h1><a id="distribution" name="distribution">Distribution</a></h1>
|
||||
<p>MochiKit - makes JavaScript suck a bit less</p>
|
||||
<ul class="simple">
|
||||
<li><a class="mochiref reference" href="Async.html">MochiKit.Async</a> - manage asynchronous tasks</li>
|
||||
<li><a class="mochiref reference" href="Base.html">MochiKit.Base</a> - functional programming and useful comparisons</li>
|
||||
<li><a class="mochiref reference" href="DOM.html">MochiKit.DOM</a> - painless DOM manipulation API</li>
|
||||
<li><a class="mochiref reference" href="Color.html">MochiKit.Color</a> - color abstraction with CSS3 support</li>
|
||||
<li><a class="mochiref reference" href="DateTime.html">MochiKit.DateTime</a> - "what time is it anyway?"</li>
|
||||
<li><a class="mochiref reference" href="Format.html">MochiKit.Format</a> - string formatting goes here</li>
|
||||
<li><a class="mochiref reference" href="Iter.html">MochiKit.Iter</a> - itertools for JavaScript; iteration made HARD,
|
||||
and then easy</li>
|
||||
<li><a class="mochiref reference" href="Logging.html">MochiKit.Logging</a> - we're all tired of <tt class="docutils literal"><span class="pre">alert()</span></tt></li>
|
||||
<li><a class="mochiref reference" href="LoggingPane.html">MochiKit.LoggingPane</a> - interactive <a class="mochiref reference" href="Logging.html">MochiKit.Logging</a>
|
||||
pane</li>
|
||||
<li><a class="mochiref reference" href="Signal.html">MochiKit.Signal</a> - simple universal event handling</li>
|
||||
<li><a class="mochiref reference" href="Visual.html">MochiKit.Visual</a> - visual effects</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="notes" name="notes">Notes</a></h1>
|
||||
<p>To turn on MochiKit's compatibility mode, do this before loading MochiKit:</p>
|
||||
<pre class="literal-block">
|
||||
<script type="text/javascript">MochiKit = {__compat__: true};</script>
|
||||
</pre>
|
||||
<p>When compatibility mode is on, you must use fully qualified names for all
|
||||
MochiKit functions (e.g. <tt class="docutils literal"><span class="pre">MochiKit.Base.map(...)</span></tt>).</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="screencasts" name="screencasts">Screencasts</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="http://mochikit.com/screencasts/MochiKit_Intro-1">MochiKit 1.1 Intro</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="see-also" name="see-also">See Also</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference" href="http://groups.google.com/group/mochikit">Google Groups: MochiKit</a>: The official mailing list for discussions
|
||||
related to development of and with MochiKit</li>
|
||||
<li><a class="reference" href="http://mochikit.com/">mochikit.com</a>: MochiKit's home on the web</li>
|
||||
<li><a class="reference" href="http://bob.pythonmac.org/">from __future__ import *</a>: Bob Ippolito's blog</li>
|
||||
<li><a class="reference" href="http://openjsan.org/doc/b/bo/bob/lib/MochiKit/">MochiKit on JSAN</a>: the JSAN distribution page for MochiKit</li>
|
||||
<li><a class="reference" href="http://del.icio.us/tag/mochikit">MochiKit tag on del.icio.us</a>: Recent bookmarks related to MochiKit</li>
|
||||
<li><a class="reference" href="http://technorati.com/tag/mochikit">MochiKit tag on Technorati</a>: Recent blog entries related to MochiKit</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="version-history" name="version-history">Version History</a></h1>
|
||||
<p>2006-04-29 v1.3.1 (bug fix release)</p>
|
||||
<ul class="simple">
|
||||
<li>Fix sendXMLHttpRequest sendContent regression</li>
|
||||
<li>Internet Explorer fix in MochiKit.Logging (printfire exception)</li>
|
||||
<li>Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async</li>
|
||||
</ul>
|
||||
<p>2006-04-26 v1.3 "warp zone"</p>
|
||||
<ul class="simple">
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)</li>
|
||||
<li>IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)</li>
|
||||
<li>New MochiKit.Base.method as a convenience form of bind that takes the
|
||||
object before the method</li>
|
||||
<li>New MochiKit.Base.flattenArguments for flattening a list of arguments to
|
||||
a single Array</li>
|
||||
<li>Refactored MochiRegExp example to use MochiKit.Signal</li>
|
||||
<li>New key_events example demonstrating use of MochiKit.Signal's key handling
|
||||
capabilities.</li>
|
||||
<li>MochiKit.DOM.createDOM API change for convenience: if attrs is a string,
|
||||
null is used and the string will be considered the first node. This
|
||||
allows for the more natural P("foo") rather than P(null, "foo").</li>
|
||||
<li>MochiKit Interpreter example refactored to use MochiKit.Signal and now
|
||||
provides multi-line input and a help() function to get MochiKit function
|
||||
signature from the documentation.</li>
|
||||
<li>Native Console Logging for the default MochiKit.Logging logger</li>
|
||||
<li>New MochiKit.Async.DeferredList, gatherResults, maybeDeferred</li>
|
||||
<li>New MochiKit.Signal example: draggable</li>
|
||||
<li>Added sanity checking to Deferred to ensure that errors happen when chaining
|
||||
is used incorrectly</li>
|
||||
<li>Opera sendXMLHttpRequest fix (sends empty string instead of null by default)</li>
|
||||
<li>Fix a bug in MochiKit.Color that incorrectly generated hex colors for
|
||||
component values smaller than 16/255.</li>
|
||||
<li>Fix a bug in MochiKit.Logging that prevented logs from being capped at a
|
||||
maximum size</li>
|
||||
<li>MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof
|
||||
Error, so that the errback chain is used instead of the callback chain.</li>
|
||||
<li>MochiKit.DOM.appendChildNodes and associated functions now append iterables
|
||||
in the correct order.</li>
|
||||
<li>New MochiKit-based SimpleTest test runner as a replacement for Test.Simple</li>
|
||||
<li>MochiKit.Base.isNull no longer matches undefined</li>
|
||||
<li>example doctypes changed to HTML4</li>
|
||||
<li>isDateLike no longer throws error on null</li>
|
||||
<li>New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt</li>
|
||||
<li>updated elementDimensions to calculate width from offsetWidth instead
|
||||
of clientWidth</li>
|
||||
<li>formContents now works with FORM tags that have a name attribute</li>
|
||||
<li>Documentation now uses MochiKit to generate a function index</li>
|
||||
</ul>
|
||||
<p>2006-01-26 v1.2 "the ocho"</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed MochiKit.Color.Color.lighterColorWithLevel</li>
|
||||
<li>Added new MochiKit.Base.findIdentical function to find the index of an
|
||||
element in an Array-like object. Uses === for identity comparison.</li>
|
||||
<li>Added new MochiKit.Base.find function to find the index of an element in
|
||||
an Array-like object. Uses compare for rich comparison.</li>
|
||||
<li>MochiKit.Base.bind will accept a string for func, which will be immediately
|
||||
looked up as self[func].</li>
|
||||
<li>MochiKit.DOM.formContents no longer skips empty form elements for Zope
|
||||
compatibility</li>
|
||||
<li>MochiKit.Iter.forEach will now catch StopIteration to break</li>
|
||||
<li>New MochiKit.DOM.elementDimensions(element) for determining the width and
|
||||
height of an element in the document</li>
|
||||
<li>MochiKit.DOM's initialization is now compatible with
|
||||
HTMLUnit + JWebUnit + Rhino</li>
|
||||
<li>MochiKit.LoggingPane will now re-use a <tt class="docutils literal"><span class="pre">_MochiKit_LoggingPane</span></tt> DIV element
|
||||
currently in the document instead of always creating one.</li>
|
||||
<li>MochiKit.Base now has operator.mul</li>
|
||||
<li>MochiKit.DOM.formContents correctly handles unchecked checkboxes that have
|
||||
a custom value attribute</li>
|
||||
<li>Added new MochiKit.Color constructors fromComputedStyle and fromText</li>
|
||||
<li>MochiKit.DOM.setNodeAttribute should work now</li>
|
||||
<li>MochiKit.DOM now has a workaround for an IE bug when setting the style
|
||||
property to a string</li>
|
||||
<li>MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the
|
||||
name and for properties</li>
|
||||
<li>MochiKit.DOM.scrapeText now walks the DOM tree in-order</li>
|
||||
<li>MochiKit.LoggingPane now sanitizes the window name to work around IE bug</li>
|
||||
<li>MochiKit.DOM now translates usemap to useMap to work around IE bug</li>
|
||||
<li>MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks</li>
|
||||
<li>Added new MochiKit.DOM documentation on element visibility</li>
|
||||
<li>New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}])
|
||||
for determining the position of an element in the document</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG</li>
|
||||
</ul>
|
||||
<p>2005-11-14 v1.1</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed a bug in numberFormatter with large numbers</li>
|
||||
<li>Massively overhauled documentation</li>
|
||||
<li>Fast-path for primitives in MochiKit.Base.compare</li>
|
||||
<li>New groupby and groupby_as_array in MochiKit.Iter</li>
|
||||
<li>Added iterator factory adapter for objects that implement iterateNext()</li>
|
||||
<li>Fixed isoTimestamp to handle timestamps with time zone correctly</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP,
|
||||
LEGEND, FIELDSET</li>
|
||||
<li>New MochiKit.DOM formContents and enhancement to queryString to support it</li>
|
||||
<li>Updated view_source example to use dp.SyntaxHighlighter 1.3.0</li>
|
||||
<li>MochiKit.LoggingPane now uses named windows based on the URL so that
|
||||
a given URL will get the same LoggingPane window after a reload
|
||||
(at the same position, etc.)</li>
|
||||
<li>MochiKit.DOM now has currentWindow() and currentDocument() context
|
||||
variables that are set with withWindow() and withDocument(). These
|
||||
context variables affect all MochiKit.DOM functionality (getElement,
|
||||
createDOM, etc.)</li>
|
||||
<li>MochiKit.Base.items will now catch and ignore exceptions for properties
|
||||
that are enumerable but not accessible (e.g. permission denied)</li>
|
||||
<li>MochiKit.Async.Deferred's addCallback/addErrback/addBoth
|
||||
now accept additional arguments that are used to create a partially
|
||||
applied function. This differs from Twisted in that the callback/errback
|
||||
result becomes the <em>last</em> argument, not the first when this feature
|
||||
is used.</li>
|
||||
<li>MochiKit.Async's doSimpleXMLHttpRequest will now accept additional
|
||||
arguments which are used to create a GET query string</li>
|
||||
<li>Did some refactoring to reduce the footprint of MochiKit by a few
|
||||
kilobytes</li>
|
||||
<li>escapeHTML to longer escapes ' (apos) and now uses
|
||||
String.replace instead of iterating over every char.</li>
|
||||
<li>Added DeferredLock to Async</li>
|
||||
<li>Renamed getElementsComputedStyle to computedStyle and moved
|
||||
it from MochiKit.Visual to MochiKit.DOM</li>
|
||||
<li>Moved all color support out of MochiKit.Visual and into MochiKit.Color</li>
|
||||
<li>Fixed range() to accept a negative step</li>
|
||||
<li>New alias to MochiKit.swapDOM called removeElement</li>
|
||||
<li>New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets
|
||||
an attribute on a node without raising, roughly equivalent to:
|
||||
updateNodeAttributes(node, {attr: value})</li>
|
||||
<li>New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of
|
||||
a node's attribute or returns null without raising</li>
|
||||
<li>Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack
|
||||
directly (addLoadEvent did not leak, since it clears the handler)</li>
|
||||
</ul>
|
||||
<p>2005-10-24 v1.0</p>
|
||||
<ul class="simple">
|
||||
<li>New interpreter example that shows usage of MochiKit.DOM to make
|
||||
an interactive JavaScript interpreter</li>
|
||||
<li>New MochiKit.LoggingPane for use with the MochiKit.Logging
|
||||
debuggingBookmarklet, with logging_pane example to show its usage</li>
|
||||
<li>New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async
|
||||
in order to provide a live regular expression matching tool</li>
|
||||
<li>Added advanced number formatting capabilities to MochiKit.Format:
|
||||
numberFormatter(pattern, placeholder="", locale="default") and
|
||||
formatLocale(locale="default")</li>
|
||||
<li>Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed
|
||||
MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE</li>
|
||||
<li>Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision)
|
||||
to MochiKit.Format</li>
|
||||
<li>MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically
|
||||
isoTimestamp(isoString) will convert them to Date objects, and
|
||||
toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC</li>
|
||||
<li>Fixed missing errback for sendXMLHttpRequest when the server does not
|
||||
respond</li>
|
||||
<li>Fixed infinite recusion bug when using roundClass("DIV", ...)</li>
|
||||
<li>Fixed a bug in MochiKit.Async wait (and callLater) that prevented them
|
||||
from being cancelled properly</li>
|
||||
<li>Workaround in MochiKit.Base bind (and partial) for functions that don't
|
||||
have an apply method, such as alert</li>
|
||||
<li>Reliably return null from the string parsing/manipulation functions if
|
||||
the input can't be coerced to a string (s + "") or the input makes no sense;
|
||||
e.g. isoTimestamp(null) and isoTimestamp("") return null</li>
|
||||
</ul>
|
||||
<p>2005-10-08 v0.90</p>
|
||||
<ul class="simple">
|
||||
<li>Fixed ISO compliance with toISODate</li>
|
||||
<li>Added missing operator.sub</li>
|
||||
<li>Placated Mozilla's strict warnings a bit</li>
|
||||
<li>Added JSON serialization and unserialization support to MochiKit.Base:
|
||||
serializeJSON, evalJSON, registerJSON. This is very similar to the repr
|
||||
API.</li>
|
||||
<li>Fixed a bug in the script loader that failed in some scenarios when a script
|
||||
tag did not have a "src" attribute (thanks Ian!)</li>
|
||||
<li>Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA,
|
||||
P, FORM</li>
|
||||
<li>Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode
|
||||
and parseQueryString, when available.</li>
|
||||
</ul>
|
||||
<p>2005-08-12 v0.80</p>
|
||||
<ul class="simple">
|
||||
<li>Source highlighting in all examples, moved to a view-source example</li>
|
||||
<li>Added some experimental syntax highlighting for the Rounded Corners example,
|
||||
via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib</li>
|
||||
<li>Use an indirect binding for the logger conveniences, so that the global
|
||||
logger could be replaced by setting MochiKit.Logger.logger to something else
|
||||
(though an observer is probably a better choice).</li>
|
||||
<li>Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent,
|
||||
which will be looked up with getElement</li>
|
||||
<li>Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of
|
||||
node.parentNode)</li>
|
||||
<li>Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success</li>
|
||||
<li>Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues</li>
|
||||
<li>Possible workaround for Safari issue with swapDOM, where it would get
|
||||
confused because two elements were in the DOM at the same time with the
|
||||
same id</li>
|
||||
<li>Added missing THEAD convenience function to MochiKit.DOM</li>
|
||||
<li>Added lstrip, rstrip, strip to MochiKit.Format</li>
|
||||
<li>Added updateNodeAttributes, appendChildNodes, replaceChildNodes to
|
||||
MochiKit.DOM</li>
|
||||
<li>MochiKit.Iter.iextend now has a fast-path for array-like objects</li>
|
||||
<li>Added HSV color space support to MochiKit.Visual</li>
|
||||
<li>Fixed a bug in the sortable_tables example, it now converts types
|
||||
correctly</li>
|
||||
<li>Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global
|
||||
scope</li>
|
||||
</ul>
|
||||
<p>2005-08-04 v0.70</p>
|
||||
<ul class="simple">
|
||||
<li>New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and
|
||||
a little TAL-ish DOM templating attribute language.</li>
|
||||
<li>sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer
|
||||
ignore requests with status == 0, which seems to happen for cached or local
|
||||
requests</li>
|
||||
<li>Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.</li>
|
||||
<li>Changed scrapeText API to return a string by default. This is API-breaking!
|
||||
It was dumb to have the default return value be the form you almost never
|
||||
want. Sorry.</li>
|
||||
<li>Added special form to swapDOM(dest, src). If src is null, dest is removed
|
||||
(where previously you'd likely get a DOM exception).</li>
|
||||
<li>Added three new functions to MochiKit.Base for dealing with URL query
|
||||
strings: urlEncode, queryString, parseQueryString</li>
|
||||
<li>MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name
|
||||
starts with "on" (e.g. "onclick"). If v is a string, it will set it to
|
||||
new Function(v).</li>
|
||||
<li>Another workaround for Internet "worst browser ever" Explorer's setAttribute
|
||||
usage in MochiKit.DOM.createDOM (checked -> defaultChecked).</li>
|
||||
<li>Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM</li>
|
||||
<li>Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller
|
||||
now!</li>
|
||||
</ul>
|
||||
<p>2005-07-29 v0.60</p>
|
||||
<ul class="simple">
|
||||
<li>Beefed up the MochiKit.DOM test suite</li>
|
||||
<li>Fixed return value for MochiKit.DOM.swapElementClass, could return
|
||||
false unexpectedly before</li>
|
||||
<li>Added an optional "parent" argument to
|
||||
MochiKit.DOM.getElementsByTagAndClassName</li>
|
||||
<li>Added a "packed" version in packed/lib/MochiKit/MochiKit.js</li>
|
||||
<li>Changed build script to rewrite the URLs in tests to account for the
|
||||
JSAN-required reorganization</li>
|
||||
<li>MochiKit.Compat to potentially work around IE 5.5 issues
|
||||
(5.0 still not supported). Test.Simple doesn't seem to work there,
|
||||
though.</li>
|
||||
<li>Several minor documentation corrections</li>
|
||||
</ul>
|
||||
<p>2005-07-27 v0.50</p>
|
||||
<ul class="simple">
|
||||
<li>Initial Release</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h1><a id="copyright" name="copyright">Copyright</a></h1>
|
||||
<p>Copyright 2005 Bob Ippolito <<a class="reference" href="mailto:bob@redivi.com">bob@redivi.com</a>>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
<a class="reference" href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or the <a class="reference" href="http://www.opensource.org/licenses/afl-2.1.php">Academic Free License v2.1</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,89 +0,0 @@
|
||||
function function_ref(fn) {
|
||||
return A({"href": fn[1], "class": "mochiref reference"}, fn[0], BR());
|
||||
};
|
||||
|
||||
function toggle_docs() {
|
||||
toggleElementClass("invisible", "show_index", "function_index");
|
||||
return false;
|
||||
};
|
||||
|
||||
function create_toc() {
|
||||
if (getElement("distribution")) {
|
||||
return global_index();
|
||||
}
|
||||
if (getElement("api-reference")) {
|
||||
return module_index();
|
||||
}
|
||||
};
|
||||
|
||||
function doXHTMLRequest(url) {
|
||||
var req = getXMLHttpRequest();
|
||||
if (req.overrideMimeType) {
|
||||
req.overrideMimeType("text/xml");
|
||||
}
|
||||
req.open("GET", url, true);
|
||||
return sendXMLHttpRequest(req).addCallback(function (res) {
|
||||
return res.responseXML.documentElement;
|
||||
});
|
||||
};
|
||||
|
||||
function load_request(href, div, doc) {
|
||||
var functions = withDocument(doc, spider_doc);
|
||||
forEach(functions, function (func) {
|
||||
// fix anchors
|
||||
if (func[1].charAt(0) == "#") {
|
||||
func[1] = href + func[1];
|
||||
}
|
||||
});
|
||||
var showLink = A({"class": "force-pointer"}, "[+]");
|
||||
var hideLink = A({"class": "force-pointer"}, "[\u2013]");
|
||||
var functionIndex = DIV({"id": "function_index", "class": "invisible"},
|
||||
hideLink,
|
||||
P(null, map(function_ref, functions))
|
||||
);
|
||||
var toggleFunc = function (e) {
|
||||
toggleElementClass("invisible", showLink, functionIndex);
|
||||
};
|
||||
connect(showLink, "onclick", toggleFunc);
|
||||
connect(hideLink, "onclick", toggleFunc);
|
||||
replaceChildNodes(div,
|
||||
showLink,
|
||||
functionIndex
|
||||
);
|
||||
};
|
||||
|
||||
function global_index() {
|
||||
var distList = getElementsByTagAndClassName("ul")[0];
|
||||
var bullets = getElementsByTagAndClassName("li", null, distList);
|
||||
for (var i = 0; i < bullets.length; i++) {
|
||||
var tag = bullets[i];
|
||||
var firstLink = getElementsByTagAndClassName("a", "mochiref", tag)[0];
|
||||
var href = getNodeAttribute(firstLink, "href");
|
||||
var div = DIV(null, "[\u2026]");
|
||||
appendChildNodes(tag, BR(), div);
|
||||
var d = doXHTMLRequest(href).addCallback(load_request, href, div);
|
||||
}
|
||||
};
|
||||
|
||||
function spider_doc() {
|
||||
return map(
|
||||
function (tag) {
|
||||
return [scrapeText(tag), getNodeAttribute(tag, "href")];
|
||||
},
|
||||
getElementsByTagAndClassName("a", "mochidef")
|
||||
);
|
||||
};
|
||||
|
||||
function module_index() {
|
||||
var sections = getElementsByTagAndClassName("div", "section");
|
||||
var ptr = sections[1];
|
||||
var ref = DIV({"class": "section"},
|
||||
H1(null, "Function Index"),
|
||||
A({"id": "show_index", "href": "#", "onclick": toggle_docs}, "[show]"),
|
||||
DIV({"id": "function_index", "class": "invisible"},
|
||||
A({"href":"#", "onclick": toggle_docs}, "[hide]"),
|
||||
P(null, map(function_ref, spider_doc()))));
|
||||
ptr.parentNode.insertBefore(ref, ptr);
|
||||
};
|
||||
|
||||
addLoadEvent(create_toc);
|
||||
@@ -1,573 +0,0 @@
|
||||
.. title:: MochiKit.Async - manage asynchronous tasks
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.Async - manage asynchronous tasks
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
var url = "/src/b/bo/bob/MochiKit.Async/META.json";
|
||||
/*
|
||||
|
||||
META.json looks something like this:
|
||||
|
||||
{"name": "MochiKit", "version": "0.5"}
|
||||
|
||||
*/
|
||||
var d = loadJSONDoc(url);
|
||||
var gotMetadata = function (meta) {
|
||||
if (MochiKit.Async.VERSION == meta.version) {
|
||||
alert("You have the newest MochiKit.Async!");
|
||||
} else {
|
||||
alert("MochiKit.Async "
|
||||
+ meta.version
|
||||
+ " is available, upgrade!");
|
||||
}
|
||||
};
|
||||
var metadataFetchFailed = function (err) {
|
||||
alert("The metadata for MochiKit.Async could not be fetched :(");
|
||||
};
|
||||
d.addCallbacks(gotMetadata, metadataFetchFailed);
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
MochiKit.Async provides facilities to manage asynchronous
|
||||
(as in AJAX [1]_) tasks. The model for asynchronous computation
|
||||
used in this module is heavily inspired by Twisted [2]_.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Deferred
|
||||
--------
|
||||
|
||||
The Deferred constructor encapsulates a single value that
|
||||
is not available yet. The most important example of this
|
||||
in the context of a web browser would be an ``XMLHttpRequest``
|
||||
to a server. The importance of the Deferred is that it
|
||||
allows a consistent API to be exposed for all asynchronous
|
||||
computations that occur exactly once.
|
||||
|
||||
The producer of the Deferred is responsible for doing all
|
||||
of the complicated work behind the scenes. This often
|
||||
means waiting for a timer to fire, or waiting for an event
|
||||
(e.g. ``onreadystatechange`` of ``XMLHttpRequest``).
|
||||
It could also be coordinating several events (e.g.
|
||||
``XMLHttpRequest`` with a timeout, or several Deferreds
|
||||
(e.g. fetching a set of XML documents that should be
|
||||
processed at the same time).
|
||||
|
||||
Since these sorts of tasks do not respond immediately, the
|
||||
producer of the Deferred does the following steps before
|
||||
returning to the consumer:
|
||||
|
||||
1. Create a ``new`` :mochiref:`Deferred();` object and keep a reference
|
||||
to it, because it will be needed later when the value is
|
||||
ready.
|
||||
2. Setup the conditions to create the value requested (e.g.
|
||||
create a new ``XMLHttpRequest``, set its
|
||||
``onreadystatechange``).
|
||||
3. Return the :mochiref:`Deferred` object.
|
||||
|
||||
Since the value is not yet ready, the consumer attaches
|
||||
a function to the Deferred that will be called when the
|
||||
value is ready. This is not unlike ``setTimeout``, or
|
||||
other similar facilities you may already be familiar with.
|
||||
The consumer can also attach an "errback" to the
|
||||
:mochiref:`Deferred`, which is a callback for error handling.
|
||||
|
||||
When the value is ready, the producer simply calls
|
||||
``myDeferred.callback(theValue)``. If an error occurred,
|
||||
it should call ``myDeferred.errback(theValue)`` instead.
|
||||
As soon as this happens, the callback that the consumer
|
||||
attached to the :mochiref:`Deferred` is called with ``theValue``
|
||||
as the only argument.
|
||||
|
||||
There are quite a few additional "advanced" features
|
||||
baked into :mochiref:`Deferred`, such as cancellation and
|
||||
callback chains, so take a look at the API
|
||||
reference if you would like to know more!
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
:mochidef:`AlreadyCalledError`:
|
||||
|
||||
Thrown by a :mochiref:`Deferred` if ``.callback`` or
|
||||
``.errback`` are called more than once.
|
||||
|
||||
|
||||
:mochidef:`BrowserComplianceError`:
|
||||
|
||||
Thrown when the JavaScript runtime is not capable of performing
|
||||
the given function. Currently, this happens if the browser
|
||||
does not support ``XMLHttpRequest``.
|
||||
|
||||
|
||||
:mochidef:`CancelledError`:
|
||||
|
||||
Thrown by a :mochiref:`Deferred` when it is cancelled,
|
||||
unless a canceller is present and throws something else.
|
||||
|
||||
|
||||
:mochidef:`GenericError`:
|
||||
|
||||
Results passed to ``.fail`` or ``.errback`` of a :mochiref:`Deferred`
|
||||
are wrapped by this ``Error`` if ``!(result instanceof Error)``.
|
||||
|
||||
|
||||
:mochidef:`XMLHttpRequestError`:
|
||||
|
||||
Thrown when an ``XMLHttpRequest`` does not complete successfully
|
||||
for any reason. The ``req`` property of the error is the failed
|
||||
``XMLHttpRequest`` object, and for convenience the ``number``
|
||||
property corresponds to ``req.status``.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
:mochidef:`Deferred()`:
|
||||
|
||||
Encapsulates a sequence of callbacks in response to a value that
|
||||
may not yet be available. This is modeled after the Deferred class
|
||||
from Twisted [3]_.
|
||||
|
||||
.. _`Twisted`: http://twistedmatrix.com/
|
||||
|
||||
Why do we want this? JavaScript has no threads, and even if it did,
|
||||
threads are hard. Deferreds are a way of abstracting non-blocking
|
||||
events, such as the final response to an ``XMLHttpRequest``.
|
||||
|
||||
The sequence of callbacks is internally represented as a list
|
||||
of 2-tuples containing the callback/errback pair. For example,
|
||||
the following call sequence::
|
||||
|
||||
var d = new Deferred();
|
||||
d.addCallback(myCallback);
|
||||
d.addErrback(myErrback);
|
||||
d.addBoth(myBoth);
|
||||
d.addCallbacks(myCallback, myErrback);
|
||||
|
||||
is translated into a :mochiref:`Deferred` with the following internal
|
||||
representation::
|
||||
|
||||
[
|
||||
[myCallback, null],
|
||||
[null, myErrback],
|
||||
[myBoth, myBoth],
|
||||
[myCallback, myErrback]
|
||||
]
|
||||
|
||||
The :mochiref:`Deferred` also keeps track of its current status (fired).
|
||||
Its status may be one of the following three values:
|
||||
|
||||
|
||||
===== ================================
|
||||
Value Condition
|
||||
===== ================================
|
||||
-1 no value yet (initial condition)
|
||||
0 success
|
||||
1 error
|
||||
===== ================================
|
||||
|
||||
A :mochiref:`Deferred` will be in the error state if one of the following
|
||||
conditions are met:
|
||||
|
||||
1. The result given to callback or errback is "``instanceof Error``"
|
||||
2. The callback or errback threw while executing. If the thrown object
|
||||
is not ``instanceof Error``, it will be wrapped with
|
||||
:mochiref:`GenericError`.
|
||||
|
||||
Otherwise, the :mochiref:`Deferred` will be in the success state. The state
|
||||
of the :mochiref:`Deferred` determines the next element in the callback
|
||||
sequence to run.
|
||||
|
||||
When a callback or errback occurs with the example deferred chain, something
|
||||
equivalent to the following will happen (imagine that exceptions are caught
|
||||
and returned as-is)::
|
||||
|
||||
// d.callback(result) or d.errback(result)
|
||||
if (!(result instanceof Error)) {
|
||||
result = myCallback(result);
|
||||
}
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
}
|
||||
result = myBoth(result);
|
||||
if (result instanceof Error) {
|
||||
result = myErrback(result);
|
||||
} else {
|
||||
result = myCallback(result);
|
||||
}
|
||||
|
||||
The result is then stored away in case another step is added to the
|
||||
callback sequence. Since the :mochiref:`Deferred` already has a value
|
||||
available, any new callbacks added will be called immediately.
|
||||
|
||||
There are two other "advanced" details about this implementation that are
|
||||
useful:
|
||||
|
||||
Callbacks are allowed to return :mochiref:`Deferred` instances,
|
||||
so you can build complicated sequences of events with (relative) ease.
|
||||
|
||||
The creator of the :mochiref:`Deferred` may specify a canceller. The
|
||||
canceller is a function that will be called if
|
||||
:mochiref:`Deferred.prototype.cancel` is called before the
|
||||
:mochiref:`Deferred` fires. You can use this to allow an
|
||||
``XMLHttpRequest`` to be cleanly cancelled, for example. Note that
|
||||
cancel will fire the :mochiref:`Deferred` with a
|
||||
:mochiref:`CancelledError` (unless your canceller throws or returns
|
||||
a different ``Error``), so errbacks should be prepared to handle that
|
||||
``Error`` gracefully for cancellable :mochiref:`Deferred` instances.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.addBoth(func)`:
|
||||
|
||||
Add the same function as both a callback and an errback as the
|
||||
next element on the callback sequence. This is useful for code
|
||||
that you want to guarantee to run, e.g. a finalizer.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the callback or
|
||||
errback will be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.addCallback(func[, ...])`:
|
||||
|
||||
Add a single callback to the end of the callback sequence.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the callback will
|
||||
be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.addCallbacks(callback, errback)`:
|
||||
|
||||
Add separate callback and errback to the end of the callback
|
||||
sequence. Either callback or errback may be ``null``,
|
||||
but not both.
|
||||
|
||||
If ``callback`` or ``errback`` returns a :mochiref:`Deferred`,
|
||||
then it will be chained (its value or error will be passed to the
|
||||
next callback). Note that once the returned ``Deferred`` is chained,
|
||||
it can no longer accept new callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.addErrback(func)`:
|
||||
|
||||
Add a single errback to the end of the callback sequence.
|
||||
|
||||
If additional arguments are given, then ``func`` will be replaced
|
||||
with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This
|
||||
differs from `Twisted`_, because the result of the errback will
|
||||
be the *last* argument passed to ``func``.
|
||||
|
||||
If ``func`` returns a :mochiref:`Deferred`, then it will be chained
|
||||
(its value or error will be passed to the next callback). Note that
|
||||
once the returned ``Deferred`` is chained, it can no longer accept new
|
||||
callbacks.
|
||||
|
||||
:mochidef:`Deferred.prototype.callback([result])`:
|
||||
|
||||
Begin the callback sequence with a non-``Error`` result. Result
|
||||
may be any value except for a :mochiref:`Deferred`.
|
||||
|
||||
Either ``.callback`` or ``.errback`` should
|
||||
be called exactly once on a :mochiref:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.cancel()`:
|
||||
|
||||
Cancels a :mochiref:`Deferred` that has not yet received a value,
|
||||
or is waiting on another :mochiref:`Deferred` as its value.
|
||||
|
||||
If a canceller is defined, the canceller is called.
|
||||
If the canceller did not return an ``Error``, or there
|
||||
was no canceller, then the errback chain is started
|
||||
with :mochiref:`CancelledError`.
|
||||
|
||||
|
||||
:mochidef:`Deferred.prototype.errback([result])`:
|
||||
|
||||
Begin the callback sequence with an error result.
|
||||
Result may be any value except for a :mochiref:`Deferred`,
|
||||
but if ``!(result instanceof Error)``, it will be wrapped
|
||||
with :mochiref:`GenericError`.
|
||||
|
||||
Either ``.callback`` or ``.errback`` should
|
||||
be called exactly once on a :mochidef:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock()`:
|
||||
|
||||
A lock for asynchronous systems.
|
||||
|
||||
The ``locked`` property of a :mochiref:`DeferredLock` will be ``true`` if
|
||||
it locked, ``false`` otherwise. Do not change this property.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock.prototype.acquire()`:
|
||||
|
||||
Attempt to acquire the lock. Returns a :mochiref:`Deferred` that fires on
|
||||
lock acquisition with the :mochiref:`DeferredLock` as the value.
|
||||
If the lock is locked, then the :mochiref:`Deferred` goes into a waiting
|
||||
list.
|
||||
|
||||
|
||||
:mochidef:`DeferredLock.prototype.release()`:
|
||||
|
||||
Release the lock. If there is a waiting list, then the first
|
||||
:mochiref:`Deferred` in that waiting list will be called back.
|
||||
|
||||
|
||||
:mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`:
|
||||
|
||||
Combine a list of :mochiref:`Deferred` into one. Track the callbacks and
|
||||
return a list of (success, result) tuples, 'success' being a boolean
|
||||
indicating whether result is a normal result or an error.
|
||||
|
||||
Once created, you have access to all :mochiref:`Deferred` methods, like
|
||||
addCallback, addErrback, addBoth. The behaviour can be changed by the
|
||||
following options:
|
||||
|
||||
``fireOnOneCallback``:
|
||||
Flag for launching the callback once the first Deferred of the list
|
||||
has returned.
|
||||
|
||||
``fireOnOneErrback``:
|
||||
Flag for calling the errback at the first error of a Deferred.
|
||||
|
||||
``consumeErrors``:
|
||||
Flag indicating that any errors raised in the Deferreds should be
|
||||
consumed by the DeferredList.
|
||||
|
||||
Example::
|
||||
|
||||
// We need to fetch data from 2 different urls
|
||||
var d1 = loadJSONDoc(url1);
|
||||
var d2 = loadJSONDoc(url2);
|
||||
var l1 = new DeferredList([d1, d2], false, false, true);
|
||||
l1.addCallback(function (resultList) {
|
||||
MochiKit.Base.map(function (result) {
|
||||
if (result[0]) {
|
||||
alert("Data is here: " + result[1]);
|
||||
} else {
|
||||
alert("Got an error: " + result[1]);
|
||||
}
|
||||
}, resultList);
|
||||
});
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`callLater(seconds, func[, args...])`:
|
||||
|
||||
Call ``func(args...)`` after at least ``seconds`` seconds have elapsed.
|
||||
This is a convenience method for::
|
||||
|
||||
func = partial.apply(extend(null, arguments, 1));
|
||||
return wait(seconds).addCallback(function (res) { return func() });
|
||||
|
||||
Returns a cancellable :mochiref:`Deferred`.
|
||||
|
||||
|
||||
:mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`:
|
||||
|
||||
Perform a simple ``XMLHttpRequest`` and wrap it with a
|
||||
:mochiref:`Deferred` that may be cancelled.
|
||||
|
||||
Note that currently, only ``200`` (OK) and ``304``
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an ``XMLHttpRequestError``.
|
||||
|
||||
``url``:
|
||||
The URL to GET
|
||||
|
||||
``queryArguments``:
|
||||
If this function is called with more than one argument, a ``"?"``
|
||||
and the result of :mochiref:`MochiKit.Base.queryString` with
|
||||
the rest of the arguments are appended to the URL.
|
||||
|
||||
For example, this will do a GET request to the URL
|
||||
``http://example.com?bar=baz``::
|
||||
|
||||
doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
|
||||
instance on success
|
||||
|
||||
|
||||
:mochidef:`evalJSONRequest(req)`:
|
||||
|
||||
Evaluate a JSON [4]_ ``XMLHttpRequest``
|
||||
|
||||
``req``:
|
||||
The request whose ``.responseText`` property is to be evaluated
|
||||
|
||||
*returns*:
|
||||
A JavaScript object
|
||||
|
||||
|
||||
:mochidef:`fail([result])`:
|
||||
|
||||
Return a :mochiref:`Deferred` that has already had ``.errback(result)``
|
||||
called.
|
||||
|
||||
See ``succeed`` documentation for rationale.
|
||||
|
||||
``result``:
|
||||
The result to give to :mochiref:`Deferred.prototype.errback(result)`.
|
||||
|
||||
*returns*:
|
||||
A ``new`` :mochiref:`Deferred()`
|
||||
|
||||
|
||||
:mochidef:`gatherResults(deferreds)`:
|
||||
|
||||
A convenience function that returns a :mochiref:`DeferredList`
|
||||
from the given ``Array`` of :mochiref:`Deferred` instances
|
||||
that will callback with an ``Array`` of just results when
|
||||
they're available, or errback on the first array.
|
||||
|
||||
|
||||
:mochidef:`getXMLHttpRequest()`:
|
||||
|
||||
Return an ``XMLHttpRequest`` compliant object for the current
|
||||
platform.
|
||||
|
||||
In order of preference:
|
||||
|
||||
- ``new XMLHttpRequest()``
|
||||
- ``new ActiveXObject('Msxml2.XMLHTTP')``
|
||||
- ``new ActiveXObject('Microsoft.XMLHTTP')``
|
||||
- ``new ActiveXObject('Msxml2.XMLHTTP.4.0')``
|
||||
|
||||
|
||||
:mochidef:`maybeDeferred(func[, argument...])`:
|
||||
|
||||
Call a ``func`` with the given arguments and ensure the result is a
|
||||
:mochiref:`Deferred`.
|
||||
|
||||
``func``:
|
||||
The function to call.
|
||||
|
||||
*returns*:
|
||||
A new :mochiref:`Deferred` based on the call to ``func``. If ``func``
|
||||
does not naturally return a :mochiref:`Deferred`, its result or error
|
||||
value will be wrapped by one.
|
||||
|
||||
|
||||
:mochidef:`loadJSONDoc(url)`:
|
||||
|
||||
Do a simple ``XMLHttpRequest`` to a URL and get the response
|
||||
as a JSON [4]_ document.
|
||||
|
||||
``url``:
|
||||
The URL to GET
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the evaluated JSON [4]_
|
||||
response upon successful ``XMLHttpRequest``
|
||||
|
||||
|
||||
:mochidef:`sendXMLHttpRequest(req[, sendContent])`:
|
||||
|
||||
Set an ``onreadystatechange`` handler on an ``XMLHttpRequest`` object
|
||||
and send it off. Will return a cancellable :mochiref:`Deferred` that will
|
||||
callback on success.
|
||||
|
||||
Note that currently, only ``200`` (OK) and ``304``
|
||||
(NOT_MODIFIED) are considered success codes at this time, other
|
||||
status codes will result in an errback with an ``XMLHttpRequestError``.
|
||||
|
||||
``req``:
|
||||
An preconfigured ``XMLHttpRequest`` object (open has been called).
|
||||
|
||||
``sendContent``:
|
||||
Optional string or DOM content to send over the ``XMLHttpRequest``.
|
||||
|
||||
*returns*:
|
||||
:mochiref:`Deferred` that will callback with the ``XMLHttpRequest``
|
||||
instance on success.
|
||||
|
||||
|
||||
:mochidef:`succeed([result])`:
|
||||
|
||||
Return a :mochiref:`Deferred` that has already had ``.callback(result)``
|
||||
called.
|
||||
|
||||
This is useful when you're writing synchronous code to an asynchronous
|
||||
interface: i.e., some code is calling you expecting a :mochiref:`Deferred`
|
||||
result, but you don't actually need to do anything asynchronous. Just
|
||||
return ``succeed(theResult)``.
|
||||
|
||||
See ``fail`` for a version of this function that uses a failing
|
||||
:mochiref:`Deferred` rather than a successful one.
|
||||
|
||||
``result``:
|
||||
The result to give to :mochiref:`Deferred.prototype.callback(result)`
|
||||
|
||||
*returns*:
|
||||
a ``new`` :mochiref:`Deferred`
|
||||
|
||||
|
||||
:mochidef:`wait(seconds[, res])`:
|
||||
|
||||
Return a new cancellable :mochiref:`Deferred` that will ``.callback(res)``
|
||||
after at least ``seconds`` seconds have elapsed.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
|
||||
.. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
|
||||
.. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
|
||||
.. [4] JSON, JavaScript Object Notation: http://json.org/
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,481 +0,0 @@
|
||||
.. title:: MochiKit.Color - color abstraction with CSS3 support
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.Color - color abstraction with CSS3 support
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
// RGB color expressions are supported
|
||||
assert(
|
||||
objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
|
||||
);
|
||||
|
||||
// So is instantiating directly from HSL or RGB values.
|
||||
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
|
||||
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );
|
||||
|
||||
// Or even SVG color keyword names, as per CSS3!
|
||||
assert( Color.fromString("aquamarine"), "#7fffd4" );
|
||||
|
||||
// NSColor-like colors built in
|
||||
assert( Color.whiteColor().toHexString() == "#ffffff" );
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
MochiKit.Color is an abstraction for handling colors and strings that
|
||||
represent colors.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha.
|
||||
It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG)
|
||||
color table.
|
||||
|
||||
All of the functionality in this module is exposed through a Color constructor
|
||||
and its prototype, but a few of its internals are available for direct use at
|
||||
module level.
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
:mochidef:`Color()`:
|
||||
|
||||
Represents a color. Component values should be integers between ``0.0``
|
||||
and ``1.0``. You should use one of the :mochiref:`Color` factory
|
||||
functions such as :mochiref:`Color.fromRGB`, :mochiref:`Color.fromHSL`,
|
||||
etc. instead of constructing :mochiref:`Color` objects directly.
|
||||
|
||||
:mochiref:`Color` instances can be compared with
|
||||
:mochiref:`MochiKit.Base.compare` (though ordering is on RGB, so is not
|
||||
particularly meaningful except for equality), and the default ``toString``
|
||||
implementation returns :mochiref:`Color.prototype.toHexString()`.
|
||||
|
||||
:mochiref:`Color` instances are immutable, and much of the architecture is
|
||||
inspired by AppKit's NSColor [1]_
|
||||
|
||||
|
||||
:mochidef:`Color.fromBackground(elem)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the background of the provided
|
||||
element. Equivalent to::
|
||||
|
||||
c = Color.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || Color.whiteColor();
|
||||
|
||||
|
||||
:mochidef:`Color.fromComputedStyle(elem, style, mozillaEquivalentCSS)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the result of
|
||||
:mochiref:`MochiKit.DOM.computedStyle(elem, style, mozillaEquivalentCSS)`
|
||||
or ``null`` if not found.
|
||||
|
||||
|
||||
:mochidef:`Color.fromHexString(hexString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given hexadecimal color string.
|
||||
For example, ``"#FFFFFF"`` would return a :mochiref:`Color` with
|
||||
RGB values ``[255/255, 255/255, 255/255]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSL(hue, saturation, lightness, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
|
||||
``lightness`` values. Values should be numbers between ``0.0`` and
|
||||
``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSLString(hslString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given decimal hsl color string.
|
||||
For example, ``"hsl(0,0%,100%)"`` would return a :mochiref:`Color` with
|
||||
HSL values ``[0/360, 0/360, 360/360]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromHSV(hue, saturation, value, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``hue``, ``saturation``,
|
||||
``value`` values. Values should be numbers between ``0.0`` and
|
||||
``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromName(colorName)`:
|
||||
|
||||
Returns a :mochiref:`Color` object corresponding to the given
|
||||
SVG 1.0 color keyword name [2]_ as per the W3C CSS3
|
||||
Color Module [3]_. ``"transparent"`` is also accepted
|
||||
as a color name, and will return :mochiref:`Color.transparentColor()`.
|
||||
|
||||
|
||||
:mochidef:`Color.fromRGB(red, green, blue, alpha=1.0)`:
|
||||
|
||||
Return a :mochiref:`Color` object from the given ``red``, ``green``,
|
||||
``blue``, and ``alpha`` values. Values should be numbers between ``0``
|
||||
and ``1.0``.
|
||||
|
||||
If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`Color.fromRGB({r: red, g: green, b: blue, a: alpha})`
|
||||
|
||||
|
||||
:mochidef:`Color.fromRGBString(rgbString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given decimal rgb color string.
|
||||
For example, ``"rgb(255,255,255)"`` would return a :mochiref:`Color` with
|
||||
RGB values ``[255/255, 255/255, 255/255]`` (white).
|
||||
|
||||
|
||||
:mochidef:`Color.fromText(elem)`:
|
||||
|
||||
Returns a :mochiref:`Color` object based on the text color of the provided
|
||||
element. Equivalent to::
|
||||
|
||||
c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
|
||||
|
||||
|
||||
:mochidef:`Color.fromString(rgbOrHexString)`:
|
||||
|
||||
Returns a :mochiref:`Color` object from the given RGB, HSL, hex, or name.
|
||||
Will return ``null`` if the string can not be parsed by any of these
|
||||
methods.
|
||||
|
||||
See :mochiref:`Color.fromHexString`, :mochiref:`Color.fromRGBString`,
|
||||
:mochiref:`Color.fromHSLString` and :mochiref:`Color.fromName` more
|
||||
information.
|
||||
|
||||
|
||||
:mochidef:`Color.namedColors()`:
|
||||
|
||||
Returns an object with properties for each SVG 1.0 color keyword
|
||||
name [2]_ supported by CSS3 [3]_. Property names are the color keyword
|
||||
name in lowercase, and the value is a string suitable for
|
||||
:mochiref:`Color.fromString()`.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithAlpha(alpha)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``alpha`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithHue(hue)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``hue`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithSaturation(saturation)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``saturation`` value (using the HSL color model).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.colorWithLightness(lightness)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but with the provided
|
||||
``lightness`` value.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.darkerColorWithLevel(level)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but darker by the given
|
||||
``level`` (between ``0`` and ``1.0``).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.lighterColorWithLevel(level)`:
|
||||
|
||||
Return a new :mochiref:`Color` based on this color, but lighter by the given
|
||||
``level`` (between ``0`` and ``1.0``).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.blendedColor(other, fraction=0.5)`:
|
||||
|
||||
Return a new :mochiref:`Color` whose RGBA component values are a weighted sum
|
||||
of this color and ``other``. Each component of the returned color
|
||||
is the ``fraction`` of other's value plus ``1 - fraction`` of this
|
||||
color's.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.isLight()`:
|
||||
|
||||
Return ``true`` if the lightness value of this color is greater than
|
||||
``0.5``.
|
||||
|
||||
Note that ``alpha`` is ignored for this calculation (color components
|
||||
are not premultiplied).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.isDark()`:
|
||||
|
||||
Return ``true`` if the lightness value of this color is less than or
|
||||
equal to ``0.5``.
|
||||
|
||||
Note that ``alpha`` is ignored for this calculation (color components
|
||||
are not premultiplied).
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toRGBString()`:
|
||||
|
||||
Return the decimal ``"rgb(red, green, blue)"`` string representation of this
|
||||
color.
|
||||
|
||||
If the alpha component is not ``1.0`` (fully opaque), the
|
||||
``"rgba(red, green, blue, alpha)"`` string representation will be used.
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toHSLString()`:
|
||||
|
||||
Return the decimal ``"hsl(hue, saturation, lightness)"``
|
||||
string representation of this color.
|
||||
|
||||
If the alpha component is not ``1.0`` (fully opaque), the
|
||||
``"hsla(hue, saturation, lightness, alpha)"`` string representation
|
||||
will be used.
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.toHexString()`:
|
||||
|
||||
Return the hexadecimal ``"#RRGGBB"`` string representation of this color.
|
||||
|
||||
Note that the alpha component is completely ignored for hexadecimal
|
||||
string representations!
|
||||
|
||||
For example::
|
||||
|
||||
assert( Color.whiteColor().toHexString() == "#FFFFFF" );
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asRGB()`:
|
||||
|
||||
Return the RGB (red, green, blue, alpha) components of this color as an
|
||||
object with ``r``, ``g``, ``b``, and ``a`` properties that have
|
||||
values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asHSL()`:
|
||||
|
||||
Return the HSL (hue, saturation, lightness, alpha) components of this
|
||||
color as an object with ``h``, ``s``, ``l`` and ``a`` properties
|
||||
that have values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.prototype.asHSV()`:
|
||||
|
||||
Return the HSV (hue, saturation, value, alpha) components of this
|
||||
color as an object with ``h``, ``s``, ``v`` and ``a`` properties
|
||||
that have values between ``0.0`` and ``1.0``.
|
||||
|
||||
|
||||
:mochidef:`Color.blackColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 0, 0
|
||||
(#000000).
|
||||
|
||||
|
||||
:mochidef:`Color.blueColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 0, 1
|
||||
(#0000ff).
|
||||
|
||||
|
||||
:mochidef:`Color.brownColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.6, 0.4, 0.2
|
||||
(#996633).
|
||||
|
||||
|
||||
:mochidef:`Color.cyanColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 1, 1
|
||||
(#00ffff).
|
||||
|
||||
|
||||
:mochidef:`Color.darkGrayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1/3, 1/3, 1/3
|
||||
(#555555).
|
||||
|
||||
|
||||
:mochidef:`Color.grayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.5, 0.5, 0.5
|
||||
(#808080).
|
||||
|
||||
|
||||
:mochidef:`Color.greenColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0, 1, 0.
|
||||
(#00ff00).
|
||||
|
||||
|
||||
:mochidef:`Color.lightGrayColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 2/3, 2/3, 2/3
|
||||
(#aaaaaa).
|
||||
|
||||
|
||||
:mochidef:`Color.magentaColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0, 1
|
||||
(#ff00ff).
|
||||
|
||||
|
||||
:mochidef:`Color.orangeColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0.5, 0
|
||||
(#ff8000).
|
||||
|
||||
|
||||
:mochidef:`Color.purpleColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 0.5, 0, 0.5
|
||||
(#800080).
|
||||
|
||||
|
||||
:mochidef:`Color.redColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 0, 0
|
||||
(#ff0000).
|
||||
|
||||
|
||||
:mochidef:`Color.whiteColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 1, 1
|
||||
(#ffffff).
|
||||
|
||||
|
||||
:mochidef:`Color.yellowColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object whose RGB values are 1, 1, 0
|
||||
(#ffff00).
|
||||
|
||||
|
||||
:mochidef:`Color.transparentColor()`:
|
||||
|
||||
Return a :mochiref:`Color` object that is completely transparent
|
||||
(has alpha component of 0).
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`clampColorComponent(num, scale)`:
|
||||
|
||||
Returns ``num * scale`` clamped between ``0`` and ``scale``.
|
||||
|
||||
:mochiref:`clampColorComponent` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`hslToRGB(hue, saturation, lightness, alpha)`:
|
||||
|
||||
Computes RGB values from the provided HSL values. The return value is a
|
||||
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})`.
|
||||
|
||||
:mochiref:`hslToRGB` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`hsvToRGB(hue, saturation, value, alpha)`:
|
||||
|
||||
Computes RGB values from the provided HSV values. The return value is a
|
||||
mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`hsvToRGB({h: hue, s: saturation, v: value, a: alpha})`.
|
||||
|
||||
:mochiref:`hsvToRGB` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`toColorPart(num)`:
|
||||
|
||||
Convert num to a zero padded hexadecimal digit for use in a hexadecimal
|
||||
color string. Num should be an integer between ``0`` and ``255``.
|
||||
|
||||
:mochiref:`toColorPart` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`rgbToHSL(red, green, blue, alpha)`:
|
||||
|
||||
Computes HSL values based on the provided RGB values. The return value is
|
||||
a mapping with ``"h"``, ``"s"``, ``"l"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`rgbToHSL({r: red, g: green, b: blue, a: alpha})`.
|
||||
|
||||
:mochiref:`rgbToHSL` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
:mochidef:`rgbToHSV(red, green, blue, alpha)`:
|
||||
|
||||
Computes HSV values based on the provided RGB values. The return value is
|
||||
a mapping with ``"h"``, ``"s"``, ``"v"`` and ``"a"`` keys.
|
||||
|
||||
Alternate form:
|
||||
:mochiref:`rgbToHSV({r: red, g: green, b: blue, a: alpha})`.
|
||||
|
||||
:mochiref:`rgbToHSV` is not exported by default when using JSAN.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html
|
||||
.. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords
|
||||
.. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
@@ -1,782 +0,0 @@
|
||||
.. title:: MochiKit.DOM - painless DOM manipulation API
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.DOM - painless DOM manipulation API
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
// put that in your document.createElement and smoke it!
|
||||
swapDOM(oldTable, newTable);
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
As you probably know, the DOM APIs are some of the most painful Java-inspired
|
||||
APIs you'll run across from a highly dynamic language. Don't worry about that
|
||||
though, because they provide a reasonable basis to build something that
|
||||
sucks a lot less.
|
||||
|
||||
MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan [2]_.
|
||||
This means you choose a tag, give it some attributes, then stuff it full
|
||||
of *whatever objects you want*. MochiKit.DOM isn't stupid, it knows that
|
||||
a string should be a text node, and that you want functions to be called,
|
||||
and that ``Array``-like objects should be expanded, and stupid ``null`` values
|
||||
should be skipped.
|
||||
|
||||
Hell, it will let you return strings from functions, and use iterators from
|
||||
:mochiref:`MochiKit.Iter`. If that's not enough, just teach it new tricks with
|
||||
:mochiref:`registerDOMConverter`. If you have never used an API like this for
|
||||
creating DOM elements, you've been wasting your damn time. Get with it!
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
- :mochiref:`MochiKit.Base`
|
||||
- :mochiref:`MochiKit.Iter`
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
DOM Coercion Rules
|
||||
------------------
|
||||
|
||||
In order of precedence, :mochiref:`createDOM` coerces given arguments to DOM
|
||||
nodes using the following rules:
|
||||
|
||||
1. Functions are called with a ``this`` of the parent
|
||||
node and their return value is subject to the
|
||||
following rules (even this one).
|
||||
2. ``undefined`` and ``null`` are ignored.
|
||||
3. Iterables (see :mochiref:`MochiKit.Iter`) are flattened
|
||||
(as if they were passed in-line as nodes) and each
|
||||
return value is subject to all of these rules.
|
||||
4. Values that look like DOM nodes (objects with a
|
||||
``.nodeType > 0``) are ``.appendChild``'ed to the created
|
||||
DOM fragment.
|
||||
5. Strings are wrapped up with ``document.createTextNode``
|
||||
6. Objects that are not strings are run through the ``domConverters``
|
||||
:mochiref:`MochiKit.Base.AdapterRegistry`
|
||||
(see :mochiref:`registerDOMConverter`).
|
||||
The value returned by the adapter is subject to these same rules (e.g.
|
||||
adapters are allowed to return a string, which will be coerced into a
|
||||
text node).
|
||||
7. If no adapter is available, ``.toString()`` is used to create a text node.
|
||||
|
||||
|
||||
Creating DOM Element Trees
|
||||
--------------------------
|
||||
|
||||
:mochiref:`createDOM` provides you with an excellent facility for creating DOM trees
|
||||
that is easy on the wrists. One of the best ways to understand how to use
|
||||
it is to take a look at an example::
|
||||
|
||||
var rows = [
|
||||
["dataA1", "dataA2", "dataA3"],
|
||||
["dataB1", "dataB2", "dataB3"]
|
||||
];
|
||||
row_display = function (row) {
|
||||
return TR(null, map(partial(TD, null), row));
|
||||
}
|
||||
var newTable = TABLE({'class': 'prettytable'},
|
||||
THEAD(null,
|
||||
row_display(["head1", "head2", "head3"])),
|
||||
TFOOT(null,
|
||||
row_display(["foot1", "foot2", "foot3"])),
|
||||
TBODY(null,
|
||||
map(row_display, rows)));
|
||||
|
||||
|
||||
This will create a table with the following visual layout (if it
|
||||
were inserted into the document DOM):
|
||||
|
||||
+--------+--------+--------+
|
||||
| head1 | head2 | head3 |
|
||||
+========+========+========+
|
||||
| dataA1 | dataA2 | dataA3 |
|
||||
+--------+--------+--------+
|
||||
| dataB1 | dataB2 | dataB3 |
|
||||
+--------+--------+--------+
|
||||
| foot1 | foot2 | foot3 |
|
||||
+--------+--------+--------+
|
||||
|
||||
Corresponding to the following HTML::
|
||||
|
||||
<table class="prettytable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>head1</td>
|
||||
<td>head2</td>
|
||||
<td>head3</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>foot1</td>
|
||||
<td>foot2</td>
|
||||
<td>foot3</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>dataA1</td>
|
||||
<td>dataA2</td>
|
||||
<td>dataA3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dataB1</td>
|
||||
<td>dataB2</td>
|
||||
<td>dataB3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
DOM Context
|
||||
-----------
|
||||
|
||||
In order to prevent having to pass a ``window`` and/or ``document``
|
||||
variable to every MochiKit.DOM function (e.g. when working with a
|
||||
child window), MochiKit.DOM maintains a context variable for each
|
||||
of them. They are managed with the :mochiref:`withWindow` and
|
||||
:mochiref:`withDocument` functions, and can be acquired with
|
||||
:mochiref:`currentWindow()` and :mochiref:`currentDocument()`
|
||||
|
||||
For example, if you are creating DOM nodes in a child window, you
|
||||
could do something like this::
|
||||
|
||||
withWindow(child, function () {
|
||||
var doc = currentDocument();
|
||||
appendChildNodes(doc.body, H1(null, "This is in the child!"));
|
||||
});
|
||||
|
||||
Note that :mochiref:`withWindow(win, ...)` also implies
|
||||
:mochiref:`withDocument(win.document, ...)`.
|
||||
|
||||
|
||||
Element Visibility
|
||||
------------------
|
||||
|
||||
The :mochiref:`hideElement` and :mochiref:`showElement` functions are
|
||||
provided as a convenience, but only work for elements that are
|
||||
``display: block``. For a general solution to showing, hiding, and checking
|
||||
the explicit visibility of elements, we recommend using a solution that
|
||||
involves a little CSS. Here's an example::
|
||||
|
||||
<style type="text/css">
|
||||
.invisible { display: none; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function toggleVisible(elem) {
|
||||
toggleElementClass("invisible", elem);
|
||||
}
|
||||
|
||||
function makeVisible(elem) {
|
||||
removeElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function makeInvisible(elem) {
|
||||
addElementClass(elem, "invisible");
|
||||
}
|
||||
|
||||
function isVisible(elem) {
|
||||
// you may also want to check for
|
||||
// getElement(elem).style.display == "none"
|
||||
return !hasElementClass(elem, "invisible");
|
||||
};
|
||||
</script>
|
||||
|
||||
MochiKit doesn't ship with such a solution, because there is no reliable and
|
||||
portable method for adding CSS rules on the fly with JavaScript.
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`$(id[, ...])`:
|
||||
|
||||
An alias for :mochiref:`getElement(id[, ...])`
|
||||
|
||||
|
||||
:mochidef:`addElementClass(element, className)`:
|
||||
|
||||
Ensure that the given ``element`` has ``className`` set as part of its
|
||||
class attribute. This will not disturb other class names.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`addLoadEvent(func)`:
|
||||
|
||||
Note that :mochiref:`addLoadEvent` can not be used in combination with
|
||||
:mochiref:`MochiKit.Signal` if the ``onload`` event is connected.
|
||||
Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs
|
||||
may be used for that same event.
|
||||
|
||||
This will stack ``window.onload`` functions on top of each other.
|
||||
Each function added will be called after ``onload`` in the
|
||||
order that they were added.
|
||||
|
||||
|
||||
:mochidef:`addToCallStack(target, path, func[, once])`:
|
||||
|
||||
Note that :mochiref:`addToCallStack` is not compatible with
|
||||
:mochiref:`MochiKit.Signal`. Once an event is connected with
|
||||
:mochiref:`MochiKit.Signal`, no other APIs may be used for that same event.
|
||||
|
||||
Set the property ``path`` of ``target`` to a function that calls the
|
||||
existing function at that property (if any), then calls ``func``.
|
||||
|
||||
If ``target[path]()`` returns exactly ``false``, then ``func`` will
|
||||
not be called.
|
||||
|
||||
If ``once`` is ``true``, then ``target[path]`` is set to ``null`` after
|
||||
the function call stack has completed.
|
||||
|
||||
If called several times for the same ``target[path]``, it will create
|
||||
a stack of functions (instead of just a pair).
|
||||
|
||||
|
||||
:mochidef:`appendChildNodes(node[, childNode[, ...]])`:
|
||||
|
||||
Append children to a DOM element using the `DOM Coercion Rules`_.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to add children to
|
||||
(if a string is given, :mochiref:`getElement(node)`
|
||||
will be used to locate the node)
|
||||
|
||||
``childNode``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`:
|
||||
|
||||
Looks up a CSS property for the given element. The element can be
|
||||
specified as either a string with the element's ID or the element
|
||||
object itself.
|
||||
|
||||
|
||||
:mochidef:`createDOM(name[, attrs[, node[, ...]]])`:
|
||||
|
||||
Create a DOM fragment in a really convenient manner, much like
|
||||
Nevow`s [1]_ stan [2]_.
|
||||
|
||||
Partially applied versions of this function for common tags are
|
||||
available as aliases:
|
||||
|
||||
- ``A``
|
||||
- ``BUTTON``
|
||||
- ``BR``
|
||||
- ``CANVAS``
|
||||
- ``DIV``
|
||||
- ``FIELDSET``
|
||||
- ``FORM``
|
||||
- ``H1``
|
||||
- ``H2``
|
||||
- ``H3``
|
||||
- ``HR``
|
||||
- ``IMG``
|
||||
- ``INPUT``
|
||||
- ``LABEL``
|
||||
- ``LEGEND``
|
||||
- ``LI``
|
||||
- ``OL``
|
||||
- ``OPTGROUP``
|
||||
- ``OPTION``
|
||||
- ``P``
|
||||
- ``PRE``
|
||||
- ``SELECT``
|
||||
- ``SPAN``
|
||||
- ``STRONG``
|
||||
- ``TABLE``
|
||||
- ``TBODY``
|
||||
- ``TD``
|
||||
- ``TEXTAREA``
|
||||
- ``TFOOT``
|
||||
- ``TH``
|
||||
- ``THEAD``
|
||||
- ``TR``
|
||||
- ``TT``
|
||||
- ``UL``
|
||||
|
||||
See `Creating DOM Element Trees`_ for a comprehensive example.
|
||||
|
||||
``name``:
|
||||
The kind of fragment to create (e.g. 'span'), such as you would
|
||||
pass to ``document.createElement``.
|
||||
|
||||
``attrs``:
|
||||
An object whose properties will be used as the attributes
|
||||
(e.g. ``{'style': 'display:block'}``), or ``null`` if no
|
||||
attributes need to be set.
|
||||
|
||||
See :mochiref:`updateNodeAttributes` for more information.
|
||||
|
||||
For convenience, if ``attrs`` is a string, ``null`` is used
|
||||
and the string will be considered the first ``node``.
|
||||
|
||||
``node``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
A DOM element
|
||||
|
||||
|
||||
:mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`:
|
||||
|
||||
Convenience function to create a partially applied createDOM
|
||||
function. You'd want to use this if you add additional convenience
|
||||
functions for creating tags, or if you find yourself creating
|
||||
a lot of tags with a bunch of the same attributes or contents.
|
||||
|
||||
See :mochiref:`createDOM` for more detailed descriptions of the arguments.
|
||||
|
||||
``tag``:
|
||||
The name of the tag
|
||||
|
||||
``attrs``:
|
||||
Optionally specify the attributes to apply
|
||||
|
||||
``node``...:
|
||||
Optionally specify any children nodes it should have
|
||||
|
||||
*returns*:
|
||||
function that takes additional arguments and calls
|
||||
:mochiref:`createDOM`
|
||||
|
||||
|
||||
:mochidef:`currentDocument()`:
|
||||
|
||||
Return the current ``document`` `DOM Context`_. This will always
|
||||
be the same as the global ``document`` unless :mochiref:`withDocument` or
|
||||
:mochiref:`withWindow` is currently executing.
|
||||
|
||||
|
||||
:mochidef:`currentWindow()`:
|
||||
|
||||
Return the current ``window`` `DOM Context`_. This will always
|
||||
be the same as the global ``window`` unless :mochiref:`withWindow` is
|
||||
currently executing.
|
||||
|
||||
|
||||
:mochidef:`elementDimensions(element)`:
|
||||
|
||||
Return the absolute pixel width and height of ``element`` as an object with
|
||||
``w`` and ``h`` properties, or ``undefined`` if ``element`` is not in the
|
||||
document. ``element`` may be specified as a string to be looked up with
|
||||
:mochiref:`getElement`, a DOM element, or trivially as an object with
|
||||
``w`` and/or ``h`` properties.
|
||||
|
||||
|
||||
:mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`:
|
||||
|
||||
Return the absolute pixel position of ``element`` in the document as an
|
||||
object with ``x`` and ``y`` properties, or ``undefined`` if ``element``
|
||||
is not in the document. ``element`` may be specified as a string to
|
||||
be looked up with :mochiref:`getElement`, a DOM element, or trivially
|
||||
as an object with ``x`` and/or ``y`` properties.
|
||||
|
||||
If ``relativeTo`` is given, then its coordinates are subtracted from
|
||||
the absolute position of ``element``, e.g.::
|
||||
|
||||
var elemPos = elementPosition(elem);
|
||||
var anotherElemPos = elementPosition(anotherElem);
|
||||
var relPos = elementPosition(elem, anotherElem);
|
||||
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
|
||||
assert( relPos.y == (elemPos.y - anotherElemPos.y) );
|
||||
|
||||
``relativeTo`` may be specified as a string to be looked up with
|
||||
:mochiref:`getElement`, a DOM element, or trivially as an object
|
||||
with ``x`` and/or ``y`` properties.
|
||||
|
||||
|
||||
:mochidef:`emitHTML(dom[, lst])`:
|
||||
|
||||
Convert a DOM tree to an ``Array`` of HTML string fragments
|
||||
|
||||
You probably want to use :mochiref:`toHTML` instead.
|
||||
|
||||
|
||||
:mochidef:`escapeHTML(s)`:
|
||||
|
||||
Make a string safe for HTML, converting the usual suspects (lt,
|
||||
gt, quot, apos, amp)
|
||||
|
||||
|
||||
:mochidef:`focusOnLoad(element)`:
|
||||
|
||||
Add an onload event to focus the given element
|
||||
|
||||
|
||||
:mochidef:`formContents(elem)`:
|
||||
|
||||
Search the DOM tree, starting at ``elem``, for any elements with a
|
||||
``name`` and ``value`` attribute. Return a 2-element ``Array`` of
|
||||
``names`` and ``values`` suitable for use with
|
||||
:mochiref:`MochiKit.Base.queryString`.
|
||||
|
||||
|
||||
:mochidef:`getElement(id[, ...])`:
|
||||
|
||||
A small quick little function to encapsulate the ``getElementById``
|
||||
method. It includes a check to ensure we can use that method.
|
||||
|
||||
If the id isn't a string, it will be returned as-is.
|
||||
|
||||
Also available as :mochiref:`$(...)` for convenience and compatibility with
|
||||
other JavaScript frameworks.
|
||||
|
||||
If multiple arguments are given, an ``Array`` will be returned.
|
||||
|
||||
|
||||
:mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`:
|
||||
|
||||
Returns an array of elements in ``parent`` that match the tag name
|
||||
and class name provided. If ``parent`` is a string, it will be looked
|
||||
up with :mochiref:`getElement`.
|
||||
|
||||
If ``tagName`` is ``null`` or ``"*"``, all elements will be searched
|
||||
for the matching class.
|
||||
|
||||
If ``className`` is ``null``, all elements matching the provided tag are
|
||||
returned.
|
||||
|
||||
|
||||
:mochidef:`getNodeAttribute(node, attr)`:
|
||||
|
||||
Get the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return ``null`` on exception).
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attr``:
|
||||
The name of the attribute
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself.
|
||||
|
||||
*returns*:
|
||||
The attribute's value, or ``null``
|
||||
|
||||
|
||||
:mochidef:`getViewportDimensions()`:
|
||||
|
||||
Return the pixel width and height of the viewport as an object with ``w``
|
||||
and ``h`` properties. ``element`` is looked up with
|
||||
:mochiref:`getElement`, so string identifiers are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`hasElementClass(element, className[, ...])`:
|
||||
|
||||
Return ``true`` if ``className`` is found on the ``element``.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`hideElement(element, ...)`:
|
||||
|
||||
Partial form of :mochiref:`setDisplayForElement`, specifically::
|
||||
|
||||
partial(setDisplayForElement, "none")
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`registerDOMConverter(name, check, wrap[, override])`:
|
||||
|
||||
Register an adapter to convert objects that match ``check(obj, ctx)``
|
||||
to a DOM element, or something that can be converted to a DOM
|
||||
element (i.e. number, bool, string, function, iterable).
|
||||
|
||||
|
||||
:mochidef:`removeElement(node)`:
|
||||
|
||||
Remove and return ``node`` from a DOM tree. This is technically
|
||||
just a convenience for :mochiref:`swapDOM(node, null)`.
|
||||
|
||||
``node``:
|
||||
the DOM element (or string id of one) to be removed
|
||||
|
||||
*returns*
|
||||
The removed element
|
||||
|
||||
|
||||
:mochidef:`removeElementClass(element, className)`:
|
||||
|
||||
Ensure that the given ``element`` does not have ``className`` set as part
|
||||
of its class attribute. This will not disturb other class names.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`replaceChildNodes(node[, childNode[, ...]])`:
|
||||
|
||||
Remove all children from the given DOM element, then append any given
|
||||
childNodes to it (by calling :mochiref:`appendChildNodes`).
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to add children to
|
||||
(if a string is given, :mochiref:`getElement(node)`
|
||||
will be used to locate the node)
|
||||
|
||||
``childNode``...:
|
||||
All additional arguments, if any, will be coerced into DOM
|
||||
nodes that are appended as children using the
|
||||
`DOM Coercion Rules`_.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`scrapeText(node[, asArray=false])`:
|
||||
|
||||
Walk a DOM tree in-order and scrape all of the text out of it as a
|
||||
``string``.
|
||||
|
||||
If ``asArray`` is ``true``, then an ``Array`` will be returned with
|
||||
each individual text node. These two are equivalent::
|
||||
|
||||
assert( scrapeText(node) == scrapeText(node, true).join("") );
|
||||
|
||||
|
||||
:mochidef:`setDisplayForElement(display, element[, ...])`:
|
||||
|
||||
Change the ``style.display`` for the given element(s). Usually
|
||||
used as the partial forms:
|
||||
|
||||
- :mochiref:`showElement(element, ...)`
|
||||
- :mochiref:`hideElement(element, ...)`
|
||||
|
||||
Elements are looked up with :mochiref:`getElement`, so string identifiers
|
||||
are acceptable.
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`setElementClass(element, className)`:
|
||||
|
||||
Set the entire class attribute of ``element`` to ``className``.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`setElementDimensions(element, dimensions[, units='px'])`:
|
||||
|
||||
Sets the dimensions of ``element`` in the document from an
|
||||
object with ``w`` and ``h`` properties.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``dimensions``:
|
||||
An object with ``w`` and ``h`` properties
|
||||
|
||||
``units``:
|
||||
Optionally set the units to use, default is ``px``
|
||||
|
||||
|
||||
:mochidef:`setElementPosition(element, position[, units='px'])`:
|
||||
|
||||
Sets the absolute position of ``element`` in the document from an
|
||||
object with ``x`` and ``y`` properties.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``position``:
|
||||
An object with ``x`` and ``y`` properties
|
||||
|
||||
``units``:
|
||||
Optionally set the units to use, default is ``px``
|
||||
|
||||
|
||||
:mochidef:`setNodeAttribute(node, attr, value)`:
|
||||
|
||||
Set the value of the given attribute for a DOM element without
|
||||
ever raising an exception (will return null on exception). If
|
||||
setting more than one attribute, you should use
|
||||
:mochiref:`updateNodeAttributes`.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attr``:
|
||||
The name of the attribute
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself.
|
||||
|
||||
``value``:
|
||||
The value of the attribute, may be an object to be merged
|
||||
(e.g. for setting style).
|
||||
|
||||
*returns*:
|
||||
The given DOM element or ``null`` on failure
|
||||
|
||||
|
||||
:mochidef:`setOpacity(element, opacity)`:
|
||||
|
||||
Sets ``opacity`` for ``element``. Valid ``opacity`` values range from 0
|
||||
(invisible) to 1 (opaque). ``element`` is looked up with
|
||||
:mochiref:`getElement`, so string identifiers are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`showElement(element, ...)`:
|
||||
|
||||
Partial form of :mochiref:`setDisplayForElement`, specifically::
|
||||
|
||||
partial(setDisplayForElement, "block")
|
||||
|
||||
For information about the caveats of using a ``style.display`` based
|
||||
show/hide mechanism, and a CSS based alternative, see
|
||||
`Element Visibility`_.
|
||||
|
||||
|
||||
:mochidef:`swapDOM(dest, src)`:
|
||||
|
||||
Replace ``dest`` in a DOM tree with ``src``, returning ``src``.
|
||||
|
||||
``dest``:
|
||||
a DOM element (or string id of one) to be replaced
|
||||
|
||||
``src``:
|
||||
the DOM element (or string id of one) to replace it with, or
|
||||
``null`` if ``dest`` is to be removed (replaced with nothing).
|
||||
|
||||
*returns*:
|
||||
a DOM element (``src``)
|
||||
|
||||
|
||||
:mochidef:`swapElementClass(element, fromClass, toClass)`:
|
||||
|
||||
If ``fromClass`` is set on ``element``, replace it with ``toClass``.
|
||||
This will not disturb other classes on that element.
|
||||
``element`` is looked up with :mochiref:`getElement`, so string identifiers
|
||||
are also acceptable.
|
||||
|
||||
|
||||
:mochidef:`toggleElementClass(className[, element[, ...]])`:
|
||||
|
||||
Toggle the presence of a given ``className`` in the class attribute
|
||||
of all given elements. All elements will be looked up with
|
||||
:mochiref:`getElement`, so string identifiers are acceptable.
|
||||
|
||||
|
||||
:mochidef:`toHTML(dom)`:
|
||||
|
||||
Convert a DOM tree to a HTML string using :mochiref:`emitHTML`
|
||||
|
||||
|
||||
:mochidef:`updateNodeAttributes(node, attrs)`:
|
||||
|
||||
Update the attributes of a DOM element from a given object.
|
||||
|
||||
``node``:
|
||||
A reference to the DOM element to update (if a string is given,
|
||||
:mochiref:`getElement(node)` will be used to locate the node)
|
||||
|
||||
``attrs``:
|
||||
An object whose properties will be used to set the attributes
|
||||
(e.g. ``{'class': 'invisible'}``), or ``null`` if no
|
||||
attributes need to be set. If an object is given for the
|
||||
attribute value (e.g. ``{'style': {'display': 'block'}}``)
|
||||
then :mochiref:`MochiKit.Base.updatetree` will be used to set that
|
||||
attribute.
|
||||
|
||||
Note that it will do the right thing for IE, so don't do
|
||||
the ``class`` -> ``className`` hack yourself, and it deals with
|
||||
setting "on..." event handlers correctly.
|
||||
|
||||
*returns*:
|
||||
The given DOM element
|
||||
|
||||
|
||||
:mochidef:`withWindow(win, func)`:
|
||||
|
||||
Call ``func`` with the ``window`` `DOM Context`_ set to ``win`` and
|
||||
the ``document`` `DOM Context`_ set to ``win.document``. When
|
||||
``func()`` returns or throws an error, the `DOM Context`_ will be
|
||||
restored to its previous state.
|
||||
|
||||
The return value of ``func()`` is returned by this function.
|
||||
|
||||
|
||||
:mochidef:`withDocument(doc, func)`:
|
||||
|
||||
Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``.
|
||||
When ``func()`` returns or throws an error, the `DOM Context`_
|
||||
will be restored to its previous state.
|
||||
|
||||
The return value of ``func()`` is returned by this function.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] Nevow, a web application construction kit for Python: http://nevow.com/
|
||||
.. [2] nevow.stan is a domain specific language for Python
|
||||
(read as "crazy getitem/call overloading abuse") that Donovan and I
|
||||
schemed up at PyCon 2003 at this super ninja Python/C++ programmer's
|
||||
(David Abrahams) hotel room. Donovan later inflicted this upon the
|
||||
masses in Nevow. Check out the Divmod project page for some
|
||||
examples: http://nevow.com/Nevow2004Tutorial.html
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
@@ -1,118 +0,0 @@
|
||||
.. title:: MochiKit.DateTime - "what time is it anyway?"
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.DateTime - "what time is it anyway?"
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
stringDate = toISOTimestamp(new Date());
|
||||
dateObject = isoTimestamp(stringDate);
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Remote servers don't give you JavaScript Date objects, and they certainly
|
||||
don't want them from you, so you need to deal with string representations
|
||||
of dates and timestamps. MochiKit.Date does that.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
None.
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`isoDate(str)`:
|
||||
|
||||
Convert an ISO 8601 date (YYYY-MM-DD) to a ``Date`` object.
|
||||
|
||||
|
||||
:mochidef:`isoTimestamp(str)`:
|
||||
|
||||
Convert any ISO 8601 [1]_ timestamp (or something reasonably close to it)
|
||||
to a ``Date`` object. Will accept the "de facto" form:
|
||||
|
||||
YYYY-MM-DD hh:mm:ss
|
||||
|
||||
or (the proper form):
|
||||
|
||||
YYYY-MM-DDThh:mm:ssZ
|
||||
|
||||
If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the
|
||||
local timezone is used.
|
||||
|
||||
|
||||
:mochidef:`toISOTime(date)`:
|
||||
|
||||
Convert a ``Date`` object to a string in the form of hh:mm:ss
|
||||
|
||||
|
||||
:mochidef:`toISOTimestamp(date, realISO=false)`:
|
||||
|
||||
Convert a ``Date`` object to something that's ALMOST but not quite an
|
||||
ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:
|
||||
|
||||
YYYY-MM-DDThh:mm:ssZ
|
||||
|
||||
However, we see junk in SQL and other places that looks like this:
|
||||
|
||||
YYYY-MM-DD hh:mm:ss
|
||||
|
||||
So, this function returns the latter form, despite its name, unless
|
||||
you pass ``true`` for ``realISO``.
|
||||
|
||||
|
||||
:mochidef:`toISODate(date)`:
|
||||
|
||||
Convert a ``Date`` object to an ISO 8601 [1]_ date string (YYYY-MM-DD)
|
||||
|
||||
|
||||
:mochidef:`americanDate(str)`:
|
||||
|
||||
Converts a MM/DD/YYYY date to a ``Date`` object
|
||||
|
||||
|
||||
:mochidef:`toPaddedAmericanDate(date)`:
|
||||
|
||||
Converts a ``Date`` object to an MM/DD/YYYY date, e.g. 01/01/2001
|
||||
|
||||
|
||||
:mochidef:`toAmericanDate(date)`:
|
||||
|
||||
Converts a ``Date`` object to an M/D/YYYY date, e.g. 1/1/2001
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] W3C profile of ISO 8601: http://www.w3.org/TR/NOTE-datetime
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
@@ -1,211 +0,0 @@
|
||||
.. title:: MochiKit.Format - string formatting goes here
|
||||
|
||||
Name
|
||||
====
|
||||
|
||||
MochiKit.Format - string formatting goes here
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
assert( truncToFixed(0.12345, 4) == "0.1234" );
|
||||
assert( roundToFixed(0.12345, 4) == "0.1235" );
|
||||
assert( twoDigitAverage(1, 0) == "0" );
|
||||
assert( twoDigitFloat(1.2345) == "1.23" );
|
||||
assert( twoDigitFloat(1) == "1" );
|
||||
assert( percentFormat(1.234567) == "123.46%" );
|
||||
assert( numberFormatter("###,###%")(125) == "12,500%" );
|
||||
assert( numberFormatter("##.000")(1.25) == "1.250" );
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Formatting strings and stringifying numbers is boring, so a couple useful
|
||||
functions in that domain live here.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
None.
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Formatting Numbers
|
||||
------------------
|
||||
|
||||
MochiKit provides an extensible number formatting facility, modeled loosely
|
||||
after the Number Format Pattern Syntax [1]_ from Java.
|
||||
:mochiref:`numberFormatter(pattern[, placeholder=""[, locale="default"])`
|
||||
returns a function that converts Number to string using the given information.
|
||||
``pattern`` is a string consisting of the following symbols:
|
||||
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| Symbol | Meaning |
|
||||
+===========+===============================================================+
|
||||
| ``-`` | If given, used as the position of the minus sign |
|
||||
| | for negative numbers. If not given, the position |
|
||||
| | to the left of the first number placeholder is used. |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| ``#`` | The placeholder for a number that does not imply zero |
|
||||
| | padding. |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| ``0`` | The placeholder for a number that implies zero padding. |
|
||||
| | If it is used to the right of a decimal separator, it |
|
||||
| | implies trailing zeros, otherwise leading zeros. |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| ``,`` | The placeholder for a "thousands separator". May be used |
|
||||
| | at most once, and it must be to the left of a decimal |
|
||||
| | separator. Will be replaced by ``locale.separator`` in the |
|
||||
| | result (the default is also ``,``). |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| ``.`` | The decimal separator. The quantity of ``#`` or ``0`` |
|
||||
| | after the decimal separator will determine the precision of |
|
||||
| | the result. If no decimal separator is present, the |
|
||||
| | fractional precision is ``0`` -- meaning that it will be |
|
||||
| | rounded to the nearest integer. |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
| ``%`` | If present, the number will be multiplied by ``100`` and |
|
||||
| | the ``%`` will be replaced by ``locale.percent``. |
|
||||
+-----------+---------------------------------------------------------------+
|
||||
|
||||
|
||||
API Reference
|
||||
=============
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
:mochidef:`formatLocale(locale="default")`:
|
||||
|
||||
Return a locale object for the given locale. ``locale`` may be either a
|
||||
string, which is looked up in the ``MochiKit.Format.LOCALE`` object, or
|
||||
a locale object. If no locale is given, ``LOCALE.default`` is used
|
||||
(equivalent to ``LOCALE.en_US``).
|
||||
|
||||
|
||||
:mochidef:`lstrip(str, chars="\\s")`:
|
||||
|
||||
Returns a string based on ``str`` with leading whitespace stripped.
|
||||
|
||||
If ``chars`` is given, then that expression will be used instead of
|
||||
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
|
||||
``[character set]``.
|
||||
|
||||
|
||||
:mochidef:`numberFormatter(pattern, placeholder="", locale="default")`:
|
||||
|
||||
Return a function ``formatNumber(aNumber)`` that formats numbers
|
||||
as a string according to the given pattern, placeholder and locale.
|
||||
|
||||
``pattern`` is a string that describes how the numbers should be formatted,
|
||||
for more information see `Formatting Numbers`_.
|
||||
|
||||
``locale`` is a string of a known locale (en_US, de_DE, fr_FR, default) or
|
||||
an object with the following fields:
|
||||
|
||||
+-----------+-----------------------------------------------------------+
|
||||
| separator | The "thousands" separator for this locale (en_US is ",") |
|
||||
+-----------+-----------------------------------------------------------+
|
||||
| decimal | The decimal separator for this locale (en_US is ".") |
|
||||
+-----------+-----------------------------------------------------------+
|
||||
| percent | The percent symbol for this locale (en_US is "%") |
|
||||
+-----------+-----------------------------------------------------------+
|
||||
|
||||
|
||||
:mochidef:`percentFormat(someFloat)`:
|
||||
|
||||
Roughly equivalent to: ``sprintf("%.2f%%", someFloat * 100)``
|
||||
|
||||
In new code, you probably want to use:
|
||||
:mochiref:`numberFormatter("#.##%")(someFloat)` instead.
|
||||
|
||||
|
||||
:mochidef:`roundToFixed(aNumber, precision)`:
|
||||
|
||||
Return a string representation of ``aNumber``, rounded to ``precision``
|
||||
digits with trailing zeros. This is similar to
|
||||
``Number.toFixed(aNumber, precision)``, but this has implementation
|
||||
consistent rounding behavior (some versions of Safari round 0.5 down!)
|
||||
and also includes preceding ``0`` for numbers less than ``1`` (Safari,
|
||||
again).
|
||||
|
||||
For example, :mochiref:`roundToFixed(0.1357, 2)` returns ``0.14`` on every
|
||||
supported platform, where some return ``.13`` for ``(0.1357).toFixed(2)``.
|
||||
|
||||
|
||||
:mochidef:`rstrip(str, chars="\\s")`:
|
||||
|
||||
Returns a string based on ``str`` with trailing whitespace stripped.
|
||||
|
||||
If ``chars`` is given, then that expression will be used instead of
|
||||
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
|
||||
``[character set]``.
|
||||
|
||||
|
||||
:mochidef:`strip(str, chars="\\s")`:
|
||||
|
||||
Returns a string based on ``str`` with leading and trailing whitespace
|
||||
stripped (equivalent to :mochiref:`lstrip(rstrip(str, chars), chars)`).
|
||||
|
||||
If ``chars`` is given, then that expression will be used instead of
|
||||
whitespace. ``chars`` should be a string suitable for use in a ``RegExp``
|
||||
``[character set]``.
|
||||
|
||||
|
||||
:mochidef:`truncToFixed(aNumber, precision)`:
|
||||
|
||||
Return a string representation of ``aNumber``, truncated to ``precision``
|
||||
digits with trailing zeros. This is similar to
|
||||
``aNumber.toFixed(precision)``, but this truncates rather than rounds and
|
||||
has implementation consistent behavior for numbers less than 1.
|
||||
Specifically, :mochiref:`truncToFixed(aNumber, precision)` will always have a
|
||||
preceding ``0`` for numbers less than ``1``.
|
||||
|
||||
For example, :mochiref:`toFixed(0.1357, 2)` returns ``0.13``.
|
||||
|
||||
|
||||
:mochidef:`twoDigitAverage(numerator, denominator)`:
|
||||
|
||||
Calculate an average from a numerator and a denominator and return
|
||||
it as a string with two digits of precision (e.g. "1.23").
|
||||
|
||||
If the denominator is 0, "0" will be returned instead of ``NaN``.
|
||||
|
||||
|
||||
:mochidef:`twoDigitFloat(someFloat)`:
|
||||
|
||||
Roughly equivalent to: ``sprintf("%.2f", someFloat)``
|
||||
|
||||
In new code, you probably want to use
|
||||
:mochiref:`numberFormatter("#.##")(someFloat)` instead.
|
||||
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
.. [1] Java Number Format Pattern Syntax:
|
||||
http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
- Bob Ippolito <bob@redivi.com>
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed
|
||||
free software; you can redistribute it and/or modify it under the terms of the
|
||||
`MIT License`_ or the `Academic Free License v2.1`_.
|
||||
|
||||
.. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user