Compare commits
7 Commits
regalloc_c
...
RDF_199901
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0fc4ac58c | ||
|
|
57a9c8988d | ||
|
|
79b5adc5e2 | ||
|
|
a73ce16b67 | ||
|
|
331af6de62 | ||
|
|
21e773b416 | ||
|
|
6d9ad8fe31 |
107
mozilla/content/xul/content/src/nsRDFDOMNodeList.cpp
Normal file
107
mozilla/content/xul/content/src/nsRDFDOMNodeList.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Helper class to implement the nsIDOMNodeList interface.
|
||||
|
||||
XXX It's probably wrong in some sense, as it uses the "naked"
|
||||
content interface to look for kids. (I assume in general this is
|
||||
bad because there may be pseudo-elements created for presentation
|
||||
that aren't visible to the DOM.)
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
|
||||
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
||||
static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID);
|
||||
|
||||
|
||||
class RDFDOMNodeListImpl : public nsIDOMNodeList {
|
||||
private:
|
||||
nsIContent* mElement;
|
||||
|
||||
public:
|
||||
RDFDOMNodeListImpl(nsIContent* element) : mElement(element) {
|
||||
NS_IF_ADDREF(mElement);
|
||||
}
|
||||
|
||||
virtual ~RDFDOMNodeListImpl(void) {
|
||||
NS_IF_RELEASE(mElement);
|
||||
}
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_IDOMNODELIST
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFDOMNodeListImpl, kIDOMNodeListIID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFDOMNodeListImpl::GetLength(PRUint32* aLength)
|
||||
{
|
||||
PRInt32 count;
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = mElement->ChildCount(count)))
|
||||
return rv;
|
||||
*aLength = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFDOMNodeListImpl::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
// XXX naive. probably breaks when there are pseudo elements or something.
|
||||
nsresult rv;
|
||||
nsIContent* contentChild;
|
||||
if (NS_FAILED(rv = mElement->ChildAt(aIndex, contentChild)))
|
||||
return rv;
|
||||
|
||||
rv = contentChild->QueryInterface(kIDOMNodeIID, (void**) aReturn);
|
||||
NS_RELEASE(contentChild);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFDOMNodeList(nsIDOMNodeList** aResult, nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
RDFDOMNodeListImpl* list = new RDFDOMNodeListImpl(aElement);
|
||||
if (! list)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(list);
|
||||
*aResult = list;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextOne(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(0)) {
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(0)) {
|
||||
index = 0;
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextZero(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(~0)) {
|
||||
for (; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(~0)) {
|
||||
for (index = 0; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
// Print the set.
|
||||
//
|
||||
void BitSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
|
||||
|
||||
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
|
||||
Int32 currentBit = i;
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
|
||||
|
||||
Int32 nextBit = nextOne(currentBit);
|
||||
if (nextBit != currentBit + 1) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
|
||||
currentBit = nextBit;
|
||||
nextBit = nextOne(nextBit);
|
||||
}
|
||||
|
||||
if (currentBit > (i+1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
|
||||
|
||||
i = currentBit;
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
@@ -1,195 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#define _BITSET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BitSet -
|
||||
|
||||
class BitSet
|
||||
{
|
||||
private:
|
||||
|
||||
#if (PR_BITS_PER_WORD == 64)
|
||||
typedef Uint64 Word;
|
||||
#elif (PR_BITS_PER_WORD == 32)
|
||||
typedef Uint32 Word;
|
||||
#endif
|
||||
|
||||
static const nBitsInWord = PR_BITS_PER_WORD;
|
||||
static const nBytesInWord = PR_BYTES_PER_WORD;
|
||||
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
|
||||
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
|
||||
|
||||
// Return the number of Word need to store the universe.
|
||||
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
|
||||
// Return the given element offset in its containing Word.
|
||||
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
|
||||
// Return the Word offset for the given element int the universe.
|
||||
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
|
||||
// Return the mask for the given bit index.
|
||||
static Word getMask(Uint8 index) {return Word(1) << index;}
|
||||
|
||||
private:
|
||||
|
||||
Uint32 universeSize; // Size of the universe
|
||||
Word* word; // universe memory.
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
BitSet(const BitSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
// Create a bitset of universeSize bits.
|
||||
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
|
||||
|
||||
// Return the size of this bitset.
|
||||
Uint32 getSize() const {return universeSize;}
|
||||
|
||||
// Clear the bitset.
|
||||
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Clear the bit at index.
|
||||
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
|
||||
// Set the bitset.
|
||||
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Set the bit at index.
|
||||
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
|
||||
// Return true if the bit at index is set.
|
||||
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
|
||||
// Union with the given bitset.
|
||||
inline void or(const BitSet& set);
|
||||
// Intersection with the given bitset.
|
||||
inline void and(const BitSet& set);
|
||||
// Difference with the given bitset.
|
||||
inline void difference(const BitSet& set);
|
||||
// Copy set.
|
||||
inline BitSet& operator = (const BitSet& set);
|
||||
// Return true if the bitset are identical.
|
||||
friend bool operator == (const BitSet& set1, const BitSet& set2);
|
||||
// Return true if the bitset are different.
|
||||
friend bool operator != (const BitSet& set1, const BitSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
|
||||
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
|
||||
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
|
||||
|
||||
// Return the first bit at set to true or -1 if none.
|
||||
Int32 firstOne() const {return nextOne(-1);}
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
Int32 nextOne(Int32 pos) const;
|
||||
// Return the first bit at set to false or -1 if none.
|
||||
Int32 firstZero() const {return nextZero(-1);}
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
Int32 nextZero(Int32 pos) const;
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return true if the walk is ordered.
|
||||
static bool isOrdered() {return true;}
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return firstOne();}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return nextOne(pos);}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == -1;}
|
||||
// Return the element corresponding to the given iterator.
|
||||
Uint32 get(iterator pos) const {return pos;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// Union with the given bitset.
|
||||
//
|
||||
inline void BitSet::or(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ |= *src++;
|
||||
}
|
||||
|
||||
// Intersection with the given bitset.
|
||||
//
|
||||
inline void BitSet::and(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= *src++;
|
||||
}
|
||||
|
||||
// Difference with the given bitset.
|
||||
//
|
||||
inline void BitSet::difference(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= ~*src++;
|
||||
}
|
||||
|
||||
// Copy the given set into this set.
|
||||
//
|
||||
inline BitSet& BitSet::operator = (const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
if (this != &set)
|
||||
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return true if the given set is identical to this set.
|
||||
inline bool operator == (const BitSet& set1, const BitSet& set2)
|
||||
{
|
||||
set1.checkUniverseCompatibility(set2);
|
||||
|
||||
if (&set1 == &set2)
|
||||
return true;
|
||||
|
||||
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
|
||||
|
||||
#endif // _BITSET_H
|
||||
@@ -1,159 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _COALESCING_H_
|
||||
#define _COALESCING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
#if 1
|
||||
// Performing an ultra conservative coalescing meens that when we look at
|
||||
// candidates (source,destination) for coalescing we need to make sure
|
||||
// that the combined interference of the source and destination register
|
||||
// will not exceed the total number of register available for the register
|
||||
// class.
|
||||
#define ULTRA_CONSERVATIVE_COALESCING
|
||||
#else
|
||||
// If we are not doing an ultra conservative coalescing we have to make sure
|
||||
// that the total number of neighbor whose degree is greater than the total
|
||||
// number of register is not greater than the total number of register.
|
||||
#undef ULTRA_CONSERVATIVE_COALESCING
|
||||
#endif
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Coalescing
|
||||
{
|
||||
static bool coalesce(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
|
||||
// Initialize the lookup table
|
||||
//
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* newRange = new RegisterName[2 * rangeCount];
|
||||
RegisterName* coalescedRange = &newRange[rangeCount];
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
init(coalescedRange, rangeCount);
|
||||
|
||||
SparseSet interferences(pool, rangeCount);
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
bool removedInstructions = false;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.lndList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
|
||||
// Walk the nodes in the loop nesting depth list.
|
||||
for (Int32 n = nNodes - 1; n >= 0; n--) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
InstructionList::iterator it = instructions.begin();
|
||||
while (!instructions.done(it)) {
|
||||
Instruction& instruction = instructions.get(it);
|
||||
it = instructions.advance(it);
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
|
||||
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
|
||||
|
||||
if (source == destination) {
|
||||
instruction.remove();
|
||||
} else if (!iGraph.interfere(source, destination)) {
|
||||
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
|
||||
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
|
||||
|
||||
#ifdef ULTRA_CONSERVATIVE_COALESCING
|
||||
interferences.clear();
|
||||
|
||||
InterferenceVector* vector;
|
||||
for (vector = sourceVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
for (vector = destinationVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
|
||||
Uint32 count = interferences.getSize();
|
||||
#else // ULTRA_CONSERVATIVE_COALESCING
|
||||
trespass("not implemented");
|
||||
Uint32 count = 0;
|
||||
#endif // ULTRA_CONSERVATIVE_COALESCING
|
||||
|
||||
if (count < 6 /* FIX: should get the number from the class */) {
|
||||
// Update the interferences vector.
|
||||
if (sourceVector == NULL) {
|
||||
iGraph.setInterferenceVector(source, destinationVector);
|
||||
sourceVector = destinationVector;
|
||||
} else if (destinationVector == NULL)
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
else {
|
||||
InterferenceVector* last = NULL;
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
|
||||
last = v;
|
||||
assert(last);
|
||||
last->next = destinationVector;
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
}
|
||||
// Update the interference matrix.
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
|
||||
RegisterName* neighbors = v->neighbors;
|
||||
for (Uint32 i = 0; i < v->count; i++) {
|
||||
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
|
||||
iGraph.setInterference(neighbor, source);
|
||||
iGraph.setInterference(neighbor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
instruction.remove();
|
||||
coalescedRange[source] = destination;
|
||||
removedInstructions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
|
||||
delete newRange;
|
||||
|
||||
return removedInstructions;
|
||||
}
|
||||
|
||||
#endif // _COALESCING_H_
|
||||
@@ -1,283 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
|
||||
#include "Coloring.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "FastBitSet.h"
|
||||
#include "FastBitMatrix.h"
|
||||
#include "CpuInfo.h"
|
||||
|
||||
bool Coloring::
|
||||
assignRegisters(FastBitMatrix& interferenceMatrix)
|
||||
{
|
||||
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
|
||||
|
||||
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
|
||||
}
|
||||
|
||||
PRInt32 Coloring::
|
||||
getLowestSpillCostRegister(FastBitSet& bitset)
|
||||
{
|
||||
PRInt32 lowest = bitset.firstOne();
|
||||
if (lowest != -1)
|
||||
{
|
||||
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
|
||||
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
|
||||
{
|
||||
cost = vReg.spillInfo.spillCost;
|
||||
lowest = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
PRUint32* Coloring::
|
||||
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
|
||||
{
|
||||
// first we construct the sets low and high. low contains all nodes of degree
|
||||
// inferior to the number of register available on the processor. All the
|
||||
// nodes with an high degree and a finite spill cost are placed in high.
|
||||
// Nodes of high degree and infinite spill cost are not included in either sets.
|
||||
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet low(pool, nRegisters);
|
||||
FastBitSet high(pool, nRegisters);
|
||||
FastBitSet stack(pool, nRegisters);
|
||||
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
{
|
||||
stack.set(i);
|
||||
vReg.colorRegister(nRegisters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
|
||||
low.set(i);
|
||||
else // if (!vReg.spillInfo.infiniteSpillCost)
|
||||
high.set(i);
|
||||
|
||||
// Set coloring info.
|
||||
vReg.spillInfo.willSpill = false;
|
||||
|
||||
switch(vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
vReg.colorRegister(LAST_GREGISTER + 1);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
vReg.colorRegister(LAST_FPREGISTER + 1);
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push the stack registers
|
||||
PRInt32 j;
|
||||
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
|
||||
*stackPtr++ = j;
|
||||
|
||||
// simplify
|
||||
while (true)
|
||||
{
|
||||
PRInt32 r;
|
||||
while ((r = getLowestSpillCostRegister(low)) != -1)
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
/* update low and high */
|
||||
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
|
||||
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
|
||||
{
|
||||
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
|
||||
// if the new interference degree of one of his neighbor becomes
|
||||
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
|
||||
|
||||
PRUint32 maxInterference = 0;
|
||||
switch (neighbor.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
maxInterference = NUMBER_OF_GREGISTERS;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
maxInterference = NUMBER_OF_FPREGISTERS;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
|
||||
{
|
||||
high.clear(j);
|
||||
low.set(j);
|
||||
}
|
||||
vReg.colorInfo.interferenceDegree--;
|
||||
interferenceMatrix.clear(r, j);
|
||||
interferenceMatrix.clear(j, r);
|
||||
}
|
||||
low.clear(r);
|
||||
|
||||
// Push this register.
|
||||
*stackPtr++ = r;
|
||||
}
|
||||
if ((r = getLowestSpillCostRegister(high)) != -1)
|
||||
{
|
||||
high.clear(r);
|
||||
low.set(r);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stackPtr;
|
||||
}
|
||||
|
||||
bool Coloring::
|
||||
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
|
||||
{
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
|
||||
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
|
||||
FastBitSet usedStack(nRegisters + 1);
|
||||
bool success = true;
|
||||
Int32 lastUsedSSR = -1;
|
||||
|
||||
// select
|
||||
while (stackPtr != stackBase)
|
||||
{
|
||||
// Pop one register.
|
||||
PRUint32 r = *--stackPtr;
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
// Stack slots coloring.
|
||||
{
|
||||
usedStack.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
|
||||
|
||||
Int32 color = usedStack.firstZero();
|
||||
vReg.colorRegister(color);
|
||||
if (color > lastUsedSSR)
|
||||
lastUsedSSR = color;
|
||||
}
|
||||
else
|
||||
// Integer & Floating point register coloring.
|
||||
{
|
||||
usedRegisters.clear();
|
||||
preColoredRegisters.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
{
|
||||
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
|
||||
usedRegisters.set(nvReg.getColor());
|
||||
if (nvReg.isPreColored())
|
||||
preColoredRegisters.set(nvReg.getPreColor());
|
||||
}
|
||||
if (vReg.hasSpecialInterference)
|
||||
usedRegisters |= vReg.specialInterference;
|
||||
|
||||
PRInt8 c = -1;
|
||||
PRInt8 maxColor = 0;
|
||||
PRInt8 firstColor = 0;
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
firstColor = FIRST_GREGISTER;
|
||||
maxColor = LAST_GREGISTER;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
firstColor = FIRST_FPREGISTER;
|
||||
maxColor = LAST_FPREGISTER;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
|
||||
if (vReg.isPreColored())
|
||||
{
|
||||
c = vReg.getPreColor();
|
||||
if (usedRegisters.test(c))
|
||||
c = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
|
||||
c = usedRegisters.nextZero(c)) {}
|
||||
}
|
||||
|
||||
if ((c >= 0) && (c <= maxColor))
|
||||
{
|
||||
vReg.colorRegister(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
|
||||
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
|
||||
vReg.spillInfo.willSpill = true;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (success)
|
||||
{
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (vReg.getColor() > LAST_GREGISTER)
|
||||
PR_ASSERT(false);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
#if NUMBER_OF_FPREGISTERS != 0
|
||||
if (vReg.getColor() > LAST_FPREGISTER)
|
||||
PR_ASSERT(false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
|
||||
return success;
|
||||
}
|
||||
#endif // NEW_LAURENTM_CODE
|
||||
@@ -1,284 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "SparseSet.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Coloring
|
||||
{
|
||||
private:
|
||||
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
|
||||
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
|
||||
|
||||
public:
|
||||
static bool color(RegisterAllocator& registerAllocator);
|
||||
static void finalColoring(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* color = registerAllocator.color;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = usePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
usePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = definePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
definePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* color = new RegisterName[rangeCount];
|
||||
registerAllocator.color = color;
|
||||
|
||||
for (Uint32 r = 1; r < rangeCount; r++)
|
||||
color[r] = RegisterName(6); // FIX;
|
||||
|
||||
// Color the preColored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID) {
|
||||
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
|
||||
}
|
||||
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
|
||||
registerAllocator.willSpill = &spill;
|
||||
SparseSet neighborColors(pool, 6); // FIX
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
bool coloringFailed = false;
|
||||
while (coloringStackPtr > coloringStack) {
|
||||
RegisterName range = *--coloringStackPtr;
|
||||
|
||||
if (!cost[range].infinite && cost[range].cost < 0) {
|
||||
coloringFailed = true;
|
||||
spill.set(range);
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
|
||||
} else {
|
||||
neighborColors.clear();
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >= 0; --i) {
|
||||
RegisterName neighborColor = color[vector->neighbors[i]];
|
||||
if (neighborColor < 6) // FIX
|
||||
neighborColors.set(neighborColor);
|
||||
}
|
||||
|
||||
if (neighborColors.getSize() == 6) { // FIX
|
||||
coloringFailed = true;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
|
||||
|
||||
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
|
||||
spill.set(range);
|
||||
} else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
|
||||
} else {
|
||||
for (Uint32 i = 0; i < 6; i++) // FIX
|
||||
if (!neighborColors.test(i)) {
|
||||
fprintf(stdout, "\twill color %d as %d\n", range, i);
|
||||
color[range] = RegisterName(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (coloringFailed) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
|
||||
spill.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
} else {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !coloringFailed;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
|
||||
{
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
SpillCost* spillCost = registerAllocator.spillCost;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
|
||||
Uint32* degree = new Uint32[rangeCount];
|
||||
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
|
||||
InterferenceVector* vector = iGraph.getInterferenceVector(i);
|
||||
degree[i] = (vector != NULL) ? vector->count : 0;
|
||||
}
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet low(pool, rangeCount);
|
||||
SparseSet high(pool, rangeCount);
|
||||
SparseSet highInfinite(pool, rangeCount);
|
||||
SparseSet preColored(pool, rangeCount);
|
||||
|
||||
// Get the precolored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID)
|
||||
preColored.set(name2range[getName(machinePtr->id)]);
|
||||
|
||||
// Insert the live ranges in the sets.
|
||||
//
|
||||
for (Uint32 range = 1; range < rangeCount; range++)
|
||||
if (!preColored.test(range))
|
||||
if (degree[range] < 6) // FIX
|
||||
low.set(range);
|
||||
else if (!spillCost[range].infinite)
|
||||
high.set(range);
|
||||
else
|
||||
highInfinite.set(range);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
|
||||
low.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
|
||||
high.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
|
||||
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
|
||||
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
RegisterName* coloringStackPtr = coloringStack;
|
||||
|
||||
while (low.getSize() != 0 || high.getSize() != 0) {
|
||||
while (low.getSize() != 0) {
|
||||
RegisterName range = RegisterName(low.getOne());
|
||||
low.clear(range);
|
||||
*coloringStackPtr++ = range;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = (vector->count - 1); i >= 0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
degree[neighbor]--;
|
||||
|
||||
if (degree[neighbor] < 6) // FIX
|
||||
if (high.test(neighbor)) {
|
||||
high.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
} else if (highInfinite.test(neighbor)) {
|
||||
highInfinite.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (high.getSize() != 0) {
|
||||
RegisterName best = RegisterName(high.getOne());
|
||||
double bestCost = spillCost[best].cost;
|
||||
double bestDegree = degree[best];
|
||||
|
||||
// Choose the next best candidate.
|
||||
//
|
||||
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
|
||||
RegisterName range = RegisterName(high.get(i));
|
||||
double thisCost = spillCost[range].cost;
|
||||
double thisDegree = degree[range];
|
||||
|
||||
if (thisCost * bestDegree < bestCost * thisDegree) {
|
||||
best = range;
|
||||
bestCost = thisCost;
|
||||
bestDegree = thisDegree;
|
||||
}
|
||||
}
|
||||
|
||||
high.clear(best);
|
||||
low.set(best);
|
||||
}
|
||||
}
|
||||
assert(highInfinite.getSize() == 0);
|
||||
|
||||
delete degree;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
|
||||
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return coloringStackPtr;
|
||||
}
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
|
||||
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
|
||||
#include "DominatorGraph.h"
|
||||
|
||||
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
|
||||
{
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
GtoV = new Uint32[nNodes + 1];
|
||||
VtoG = new Uint32[nNodes + 1];
|
||||
|
||||
Uint32 v = 1;
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
VtoG[v] = n;
|
||||
GtoV[n] = v++;
|
||||
}
|
||||
|
||||
// Initialize all the 1-based arrays.
|
||||
//
|
||||
parent = new Uint32[v];
|
||||
semi = new Uint32[v];
|
||||
vertex = new Uint32[v];
|
||||
label = new Uint32[v];
|
||||
size = new Uint32[v];
|
||||
ancestor = new Uint32[v];
|
||||
child = new Uint32[v];
|
||||
dom = new Uint32[v];
|
||||
bucket = new DGLinkedList*[v];
|
||||
|
||||
memset(semi, '\0', v * sizeof(Uint32));
|
||||
memset(bucket, '\0', v * sizeof(DGLinkedList*));
|
||||
|
||||
vCount = v;
|
||||
|
||||
build();
|
||||
|
||||
delete parent;
|
||||
delete semi;
|
||||
delete vertex;
|
||||
delete label;
|
||||
delete size;
|
||||
delete ancestor;
|
||||
delete child;
|
||||
delete dom;
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
|
||||
{
|
||||
semi[vx] = ++n;
|
||||
vertex[n] = label[vx] = vx;
|
||||
ancestor[vx] = child[vx] = 0;
|
||||
size[vx] = 1;
|
||||
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
|
||||
ControlEdge* successorEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
|
||||
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
|
||||
if (semi[w] == 0) {
|
||||
parent[w] = vx;
|
||||
n = DFS(w, n);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
|
||||
{
|
||||
Uint32 s = w;
|
||||
|
||||
while (semi[label[w]] < semi[label[child[s]]]) {
|
||||
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
|
||||
ancestor[child[s]] = s;
|
||||
child[s] = child[child[s]];
|
||||
} else {
|
||||
size[child[s]] = size[s];
|
||||
s = ancestor[s] = child[s];
|
||||
}
|
||||
}
|
||||
label[s] = label[w];
|
||||
size[vx] += size[w];
|
||||
if(size[vx] < (size[w] << 1)) {
|
||||
Uint32 t = s;
|
||||
s = child[vx];
|
||||
child[vx] = t;
|
||||
}
|
||||
while( s != 0 ) {
|
||||
ancestor[s] = vx;
|
||||
s = child[s];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DominatorGraph::COMPRESS(Uint32 vx)
|
||||
{
|
||||
if(ancestor[ancestor[vx]] != 0) {
|
||||
COMPRESS(ancestor[vx]);
|
||||
if(semi[label[ancestor[vx]]] < semi[label[vx]])
|
||||
label[vx] = label[ancestor[vx]];
|
||||
ancestor[vx] = ancestor[ancestor[vx]];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::EVAL(Uint32 vx)
|
||||
{
|
||||
if(ancestor[vx] == 0)
|
||||
return label[vx];
|
||||
COMPRESS(vx);
|
||||
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
|
||||
}
|
||||
|
||||
void DominatorGraph::build()
|
||||
{
|
||||
Uint32 n = DFS(GtoV[0], 0);
|
||||
size[0] = label[0] = semi[0];
|
||||
|
||||
for (Uint32 i = n; i >= 2; i--) {
|
||||
Uint32 w = vertex[i];
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
|
||||
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
|
||||
Uint32 u = EVAL(vx);
|
||||
|
||||
if(semi[u] < semi[w])
|
||||
semi[w] = semi[u];
|
||||
}
|
||||
|
||||
DGLinkedList* elem = new DGLinkedList();
|
||||
elem->next = bucket[vertex[semi[w]]];
|
||||
elem->index = w;
|
||||
bucket[vertex[semi[w]]] = elem;
|
||||
|
||||
LINK(parent[w], w);
|
||||
|
||||
elem = bucket[parent[w]];
|
||||
while(elem != NULL) {
|
||||
Uint32 vx = elem->index;
|
||||
Uint32 u = EVAL(vx);
|
||||
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
memset(size, '\0', n * sizeof(Uint32));
|
||||
Pool& pool = controlGraph.pool;
|
||||
nodes = new(pool) DGNode[n];
|
||||
|
||||
for(Uint32 j = 2; j <= n; j++) {
|
||||
Uint32 w = vertex[j];
|
||||
Uint32 d = dom[w];
|
||||
if(d != vertex[semi[w]]) {
|
||||
d = dom[d];
|
||||
dom[w] = d;
|
||||
}
|
||||
size[d]++;
|
||||
}
|
||||
dom[GtoV[0]] = 0;
|
||||
|
||||
for (Uint32 k = 1; k <= n; k++) {
|
||||
DGNode& node = nodes[VtoG[k]];
|
||||
Uint32 count = size[k];
|
||||
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
|
||||
}
|
||||
|
||||
for (Uint32 l = 2; l <= n; l++)
|
||||
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void DominatorGraph::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
for (Uint32 i = 0; i < nNodes; i++) {
|
||||
DGNode& node = nodes[i];
|
||||
if (node.successorsBegin != node.successorsEnd) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
|
||||
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DOMINATOR_GRAPH_H_
|
||||
#define _DOMINATOR_GRAPH_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
|
||||
class ControlGraph;
|
||||
|
||||
struct DGNode
|
||||
{
|
||||
Uint32* successorsBegin;
|
||||
Uint32* successorsEnd;
|
||||
};
|
||||
|
||||
struct DGLinkedList
|
||||
{
|
||||
DGLinkedList* next;
|
||||
Uint32 index;
|
||||
};
|
||||
|
||||
class DominatorGraph
|
||||
{
|
||||
private:
|
||||
|
||||
ControlGraph& controlGraph;
|
||||
|
||||
Uint32 vCount;
|
||||
|
||||
Uint32* VtoG;
|
||||
Uint32* GtoV;
|
||||
Uint32* parent;
|
||||
Uint32* semi;
|
||||
Uint32* vertex;
|
||||
Uint32* label;
|
||||
Uint32* size;
|
||||
Uint32* ancestor;
|
||||
Uint32* child;
|
||||
Uint32* dom;
|
||||
DGLinkedList** bucket;
|
||||
DGNode* nodes;
|
||||
|
||||
private:
|
||||
|
||||
void build();
|
||||
|
||||
Uint32 DFS(Uint32 vx, Uint32 n);
|
||||
void LINK(Uint32 vx, Uint32 w);
|
||||
void COMPRESS(Uint32 vx);
|
||||
Uint32 EVAL(Uint32 vx);
|
||||
|
||||
public:
|
||||
|
||||
DominatorGraph(ControlGraph& controlGraph);
|
||||
|
||||
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
|
||||
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
#endif // _DOMINATOR_GRAPH_H_
|
||||
@@ -1,20 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashSet.h"
|
||||
@@ -1,97 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_SET_H_
|
||||
#define _HASH_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
struct HashSetElement
|
||||
{
|
||||
Uint32 index;
|
||||
HashSetElement* next;
|
||||
};
|
||||
|
||||
class HashSet
|
||||
{
|
||||
private:
|
||||
|
||||
static const hashSize = 64;
|
||||
|
||||
// Return the hash code for the given element index.
|
||||
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
|
||||
|
||||
private:
|
||||
|
||||
Pool& allocationPool;
|
||||
HashSetElement** bucket;
|
||||
HashSetElement* free;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
HashSet(const HashSet&);
|
||||
// No copy operator.
|
||||
void operator = (const HashSet&);
|
||||
|
||||
public:
|
||||
|
||||
// Create a new HashSet.
|
||||
inline HashSet(Pool& pool, Uint32 universeSize);
|
||||
|
||||
// Clear the hashset.
|
||||
void clear();
|
||||
// Clear the element for the given index.
|
||||
void clear(Uint32 index);
|
||||
// Set the element for the given index.
|
||||
void set(Uint32 index);
|
||||
// Return true if the element at index is a member.
|
||||
bool test(Uint32 index) const;
|
||||
// Union with the given hashset.
|
||||
inline void or(const HashSet& set);
|
||||
// Intersection with the given hashset.
|
||||
inline void and(const HashSet& set);
|
||||
// Difference with the given hashset.
|
||||
inline void difference(const HashSet& set);
|
||||
|
||||
// Logical operators.
|
||||
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
|
||||
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
|
||||
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef HashSetElement* iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const;
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const;
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == NULL;}
|
||||
};
|
||||
|
||||
|
||||
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
|
||||
: allocationPool(pool), free(NULL)
|
||||
{
|
||||
bucket = new(pool) HashSetElement*[hashSize];
|
||||
memset(bucket, '\0', sizeof(HashSetElement*));
|
||||
}
|
||||
|
||||
#endif // _HASH_SET_H_
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INDEXED_POOL_H_
|
||||
#define _INDEXED_POOL_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
|
||||
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
|
||||
// IndexedObject.
|
||||
//
|
||||
// When the indexed pool is ask to allocate and initialize a new object (using
|
||||
// the operator new(anIndexedPool) it will zero the memory used to store the
|
||||
// object and initialize the field 'index' of this object to its position in
|
||||
// the pool.
|
||||
//
|
||||
// An object allocated by the indexed pool can be freed by calling the method
|
||||
// IndexedPool::release(IndexedElement& objectIndex).
|
||||
//
|
||||
// example:
|
||||
//
|
||||
// IndexedPool<IndexedElement> elementPool;
|
||||
//
|
||||
// IndexedElement& element1 = *new(elementPool) IndexedElement();
|
||||
// IndexedElement& element2 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// indexedPool.release(element1);
|
||||
// IndexedElement& element3 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// At this point element1 is no longer a valid object, element2 is at
|
||||
// index 2 and element3 is at index 1.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedObject -
|
||||
//
|
||||
|
||||
template<class Object>
|
||||
struct IndexedObject
|
||||
{
|
||||
Uint32 index; // Index in the pool.
|
||||
Object* next; // Used to link IndexedObject together.
|
||||
|
||||
Uint32 getIndex() {return index;}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObject> -
|
||||
//
|
||||
|
||||
template <class IndexedObject>
|
||||
class IndexedPool
|
||||
{
|
||||
private:
|
||||
|
||||
static const blockSize = 4; // Size of one block.
|
||||
|
||||
Uint32 nBlocks; // Number of blocks in the pool.
|
||||
IndexedObject** block; // Array of block pointers.
|
||||
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
|
||||
Uint32 nextIndex; // Index of the next free object in the last block.
|
||||
|
||||
private:
|
||||
|
||||
void allocateAnotherBlock();
|
||||
IndexedObject& newObject();
|
||||
|
||||
public:
|
||||
|
||||
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
|
||||
~IndexedPool();
|
||||
|
||||
IndexedObject& get(Uint32 index) const;
|
||||
void release(IndexedObject& object);
|
||||
|
||||
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
|
||||
|
||||
// Return the universe size.
|
||||
Uint32 getSize() {return nextIndex;}
|
||||
|
||||
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
|
||||
};
|
||||
|
||||
// Free all the memory allocated for this object.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedPool<IndexedObject>::~IndexedPool()
|
||||
{
|
||||
for (Uint32 n = 0; n < nBlocks; n++)
|
||||
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
|
||||
}
|
||||
|
||||
// Release the given. This object will be iserted in the chained
|
||||
// list of free IndexedObjects. To minimize the fragmentation the chained list
|
||||
// is ordered by ascending indexes.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::release(IndexedObject& object)
|
||||
{
|
||||
Uint32 index = object.index;
|
||||
IndexedObject* list = freeObjects;
|
||||
|
||||
assert(&object == &get(index)); // Make sure that object is owned by this pool.
|
||||
|
||||
if (list == NULL) { // The list is empty.
|
||||
freeObjects = &object;
|
||||
object.next = NULL;
|
||||
} else { // The list contains at least 1 element.
|
||||
if (index < list->index) { // insert as first element.
|
||||
freeObjects = &object;
|
||||
object.next = list;
|
||||
} else { // Find this object's place.
|
||||
while ((list->next) != NULL && (list->next->index < index))
|
||||
list = list->next;
|
||||
|
||||
object.next = list->next;
|
||||
list->next = &object;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Sanity check to be sure that the list is correctly ordered.
|
||||
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
|
||||
if (obj->next != NULL)
|
||||
assert(obj->index < obj->next->index);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a new block of IndexedObjects. We will allocate the memory to
|
||||
// store IndexedPool::blockSize IndexedObject and the new Array of block
|
||||
// pointers.
|
||||
// The newly created IndexedObjects will not be initialized.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::allocateAnotherBlock()
|
||||
{
|
||||
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
|
||||
|
||||
memcpy(memory, block, nBlocks * sizeof(Uint32));
|
||||
|
||||
block = (IndexedObject **) memory;
|
||||
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
|
||||
|
||||
block[nBlocks] = &objects[-(nBlocks * blockSize)];
|
||||
nBlocks++;
|
||||
}
|
||||
|
||||
// Return the IndexedObject at the position 'index' in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
|
||||
{
|
||||
Uint32 blockIndex = index / blockSize;
|
||||
assert(blockIndex < nBlocks);
|
||||
|
||||
return block[blockIndex][index];
|
||||
}
|
||||
|
||||
// Return the reference of an unused object in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::newObject()
|
||||
{
|
||||
if (freeObjects != NULL) {
|
||||
IndexedObject& newObject = *freeObjects;
|
||||
freeObjects = newObject.next;
|
||||
return newObject;
|
||||
}
|
||||
|
||||
Uint32 nextIndex = this->nextIndex++;
|
||||
Uint32 blockIndex = nextIndex / blockSize;
|
||||
|
||||
while (blockIndex >= nBlocks)
|
||||
allocateAnotherBlock();
|
||||
|
||||
IndexedObject& newObject = block[blockIndex][nextIndex];
|
||||
newObject.index = nextIndex;
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
// Return the address of the next unsused object in the given
|
||||
// indexed pool. The field index of the newly allocated object
|
||||
// will be initialized to the corresponding index of this object
|
||||
// in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
|
||||
{
|
||||
assert(size == sizeof(IndexedObject));
|
||||
return (void *) &pool.newObject();
|
||||
}
|
||||
|
||||
#endif // _INDEXED_POOL_H_
|
||||
@@ -1,258 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFERENCE_GRAPH_H_
|
||||
#define _INTERFERENCE_GRAPH_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
struct InterferenceVector
|
||||
{
|
||||
Uint32 count;
|
||||
InterferenceVector* next;
|
||||
RegisterName* neighbors;
|
||||
|
||||
InterferenceVector() : count(0), next(NULL) {}
|
||||
};
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class InterferenceGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* interferences;
|
||||
InterferenceVector** vector;
|
||||
Uint32* offset;
|
||||
Uint32 rangeCount;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
InterferenceGraph(const InterferenceGraph&);
|
||||
// No copy operator.
|
||||
void operator = (const InterferenceGraph&);
|
||||
|
||||
// Check if reg is a member of the universe.
|
||||
void checkMember(RegisterName name) {assert(name < rangeCount);}
|
||||
// Return the edge index for the interference between name1 and name2.
|
||||
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
|
||||
|
||||
public:
|
||||
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
// Calculate the interferences.
|
||||
void build();
|
||||
// Return true if reg1 and reg2 interfere.
|
||||
bool interfere(RegisterName name1, RegisterName name2);
|
||||
// Return the interference vector for the given register or NULL if there is none.
|
||||
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
|
||||
// Set the interference between name1 and name2.
|
||||
void setInterference(RegisterName name1, RegisterName name2);
|
||||
// Set the interference vector for the given register.
|
||||
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
|
||||
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the interferences.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
// Initialize the structures.
|
||||
//
|
||||
offset = new(pool) Uint32[rangeCount + 1];
|
||||
vector = new(pool) InterferenceVector*[rangeCount];
|
||||
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
|
||||
|
||||
Uint32 o = 0;
|
||||
offset[0] = 0;
|
||||
for (Uint32 i = 1; i <= rangeCount; ++i) {
|
||||
offset[i] = o;
|
||||
o += i;
|
||||
}
|
||||
|
||||
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
|
||||
registerAllocator.liveness = liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
// Create the interferences.
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
|
||||
RegisterName live = RegisterName(currentLive.get(e));
|
||||
|
||||
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
|
||||
|
||||
if (vector[define] == NULL)
|
||||
vector[define] = new(pool) InterferenceVector();
|
||||
vector[define]->count++;
|
||||
|
||||
if (vector[live] == NULL)
|
||||
vector[live] = new(pool) InterferenceVector();
|
||||
vector[live]->count++;
|
||||
|
||||
setInterference(live, define);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now update the liveness.
|
||||
//
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the memory to store the interferences.
|
||||
//
|
||||
for (Uint32 e = 0; e < rangeCount; e++)
|
||||
if (vector[e] != NULL) {
|
||||
InterferenceVector& v = *vector[e];
|
||||
v.neighbors = new(pool) RegisterName[v.count];
|
||||
v.count = 0;
|
||||
}
|
||||
|
||||
// Initialize the edges.
|
||||
//
|
||||
if (RegisterPressure::Set::isOrdered()) {
|
||||
RegisterName name1 = RegisterName(0);
|
||||
|
||||
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
|
||||
Uint32 interferenceIndex = interferences->get(i);
|
||||
|
||||
while(interferenceIndex >= offset[name1 + 1])
|
||||
name1 = RegisterName(name1 + 1);
|
||||
|
||||
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
|
||||
|
||||
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
|
||||
|
||||
assert(interfere(name1, name2));
|
||||
|
||||
InterferenceVector& vector1 = *vector[name1];
|
||||
vector1.neighbors[vector1.count++] = name2;
|
||||
|
||||
InterferenceVector& vector2 = *vector[name2];
|
||||
vector2.neighbors[vector2.count++] = name1;
|
||||
}
|
||||
} else {
|
||||
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
checkMember(name1); checkMember(name2);
|
||||
assert(name1 != name2); // This is not possible.
|
||||
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
interferences->set(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
return interferences->test(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
if (vector[i] != NULL) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
|
||||
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
|
||||
for (Uint32 j = 0; j < v->count; j++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
|
||||
if (v->next != NULL || j != (v->count - 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
|
||||
}
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _INTERFERENCE_GRAPH_H_
|
||||
@@ -1,87 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_H_
|
||||
#define _LIVE_RANGE_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LiveRange
|
||||
{
|
||||
static void build(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
// Intialize the lookup table.
|
||||
//
|
||||
Uint32 nameCount = registerAllocator.nameCount;
|
||||
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
|
||||
RegisterName* rangeName = &nameTable[nameCount];
|
||||
|
||||
init(rangeName, nameCount);
|
||||
|
||||
// Walk the graph.
|
||||
//
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
SparseSet destination(registerAllocator.pool, nameCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
|
||||
destination.clear();
|
||||
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
Instruction& phiNode = phiNodes.get(i);
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
|
||||
}
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
RegisterName destinationRoot = findRoot(destinationName, rangeName);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName sourceName = usePtr->getRegisterName();
|
||||
RegisterName sourceRoot = findRoot(sourceName, rangeName);
|
||||
|
||||
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
|
||||
rangeName[sourceRoot] = destinationRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
|
||||
}
|
||||
|
||||
#endif // _LIVE_RANGE_H_
|
||||
@@ -1,163 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_GRAPH_
|
||||
#define _LIVE_RANGE_GRAPH_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class LiveRangeGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* edges;
|
||||
Uint32 rangeCount;
|
||||
|
||||
public:
|
||||
//
|
||||
//
|
||||
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
//
|
||||
//
|
||||
void build();
|
||||
|
||||
//
|
||||
//
|
||||
void addEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
//
|
||||
//
|
||||
bool haveEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (define != live && registerAllocator.canInterfere(define, live))
|
||||
addEdge(define, live);
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName use = name2range[usePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (use != live && registerAllocator.canInterfere(use, live))
|
||||
addEdge(use, live);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
edges->set(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
return edges->test(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVE_RANGE_GRAPH_
|
||||
@@ -1,21 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIVENESS_H_
|
||||
#define _LIVENESS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LivenessInfo -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LivenessInfo
|
||||
{
|
||||
RegisterPressure::Set* liveIn;
|
||||
RegisterPressure::Set* liveOut;
|
||||
DEBUG_LOG_ONLY(Uint32 size);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Liveness
|
||||
//
|
||||
// The liveness is defined by the following data-flow equations:
|
||||
//
|
||||
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
|
||||
// LiveOut(n) = U LiveIn(s) (s a successor of n).
|
||||
//
|
||||
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
|
||||
// is the set of defined registers in the block n, LiveIn(n) is the set of
|
||||
// live registers at the begining of the block n and LiveOut(n) is the set
|
||||
// of live registers at the end of the block n.
|
||||
//
|
||||
//
|
||||
// We will compute the liveness analysis in two stages:
|
||||
//
|
||||
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
|
||||
// for each block n.
|
||||
// 2- Perform a backward data-flow analysis to propagate the liveness information
|
||||
// through the entire control-flow graph.
|
||||
//
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Liveness
|
||||
{
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = name2range[usePtr->getRegisterName()];
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, rangeCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* usedByPhiNodes = NULL;
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
|
||||
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
|
||||
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
|
||||
currentKilled.set(define.getRegisterName());
|
||||
|
||||
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
|
||||
const ControlEdgeList& predecessors = node.getPredecessors();
|
||||
ControlEdgeList::iterator p = predecessors.begin();
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
|
||||
if (usePtr->isRegister())
|
||||
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
|
||||
}
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = usePtr->getRegisterName();
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, nameCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// Insert the phiNodes contribution.
|
||||
if (usedByPhiNodes != NULL)
|
||||
temp |= usedByPhiNodes[n];
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
for (Uint32 n = 0; n < size; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
|
||||
liveIn[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
|
||||
liveOut[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVENESS_H_
|
||||
@@ -1,40 +0,0 @@
|
||||
#! gmake
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
MODULE_NAME = RegisterAllocator
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DEPTH)/Utilities/General \
|
||||
-I$(DEPTH)/Utilities/zlib \
|
||||
-I$(DEPTH)/Runtime/ClassReader \
|
||||
-I$(DEPTH)/Runtime/NativeMethods \
|
||||
-I$(DEPTH)/Runtime/System \
|
||||
-I$(DEPTH)/Runtime/ClassInfo \
|
||||
-I$(DEPTH)/Runtime/FileReader \
|
||||
-I$(DEPTH)/Compiler/PrimitiveGraph \
|
||||
-I$(DEPTH)/Compiler/FrontEnd \
|
||||
-I$(DEPTH)/Compiler/Optimizer \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
|
||||
-I$(DEPTH)/Compiler/RegisterAllocator \
|
||||
-I$(DEPTH)/Driver/StandAloneJava \
|
||||
-I$(DEPTH)/Debugger \
|
||||
$(NULL)
|
||||
|
||||
CXXSRCS = \
|
||||
RegisterAllocator.cpp \
|
||||
RegisterAllocatorTools.cpp \
|
||||
DominatorGraph.cpp \
|
||||
VirtualRegister.cpp \
|
||||
BitSet.cpp \
|
||||
SparseSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
libs:: $(MODULE)
|
||||
@@ -1,392 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _PHI_NODE_REMOVER_H_
|
||||
#define _PHI_NODE_REMOVER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "DominatorGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "Liveness.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterNameNode -
|
||||
|
||||
struct RegisterNameNode
|
||||
{
|
||||
RegisterNameNode* next;
|
||||
RegisterName newName;
|
||||
Uint32 nextPushed;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CopyData -
|
||||
|
||||
struct CopyData
|
||||
{
|
||||
RegisterName source;
|
||||
RegisterClassKind classKind;
|
||||
Uint32 useCount;
|
||||
bool isLiveOut;
|
||||
RegisterName sourceNameToUse;
|
||||
RegisterName temporaryName;
|
||||
RegisterNameNode* newName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PhiNodeRemover<RegisterPressure> -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct PhiNodeRemover
|
||||
{
|
||||
// Replace the phi nodes by copy instructions.
|
||||
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
// Split some of the critical edges and return true if there are still some
|
||||
// in the graph after that.
|
||||
//
|
||||
static bool splitCriticalEdges(ControlGraph& /*cg*/)
|
||||
{
|
||||
// FIX: not implemented.
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
|
||||
{
|
||||
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
|
||||
|
||||
if (pushed.test(oldName))
|
||||
(*stack)->newName = newName;
|
||||
else {
|
||||
newNode.newName = newName;
|
||||
newNode.nextPushed = *nodeListPointer;
|
||||
*nodeListPointer = oldName;
|
||||
newNode.next = *stack;
|
||||
*stack = &newNode;
|
||||
pushed.set(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Initialize the local variables.
|
||||
//
|
||||
|
||||
// When we insert the copies we will also need to create new VirtualRegisters for
|
||||
// the insertion of temporaries. The maximum number of temporary register will not
|
||||
// exceed the number of phiNodes in the primitive graph.
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
Uint32 maxNameCount = nameCount;
|
||||
for (Uint32 n = 0; n < nNodes; n++)
|
||||
maxNameCount += nodes[n]->getPhiNodes().length();
|
||||
|
||||
// If the CFG contains some critical edges (backward edge which source has more than one
|
||||
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
|
||||
// information to be able to insert temporary copies.
|
||||
RegisterPressure::Set* liveOut = NULL;
|
||||
if (splitCriticalEdges(controlGraph))
|
||||
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
|
||||
|
||||
DominatorGraph dGraph(controlGraph);
|
||||
|
||||
SparseSet pushed(pool, maxNameCount);
|
||||
SparseSet destinationList(pool, maxNameCount);
|
||||
SparseSet workList(pool, maxNameCount);
|
||||
|
||||
CopyData* copyStats = new(pool) CopyData[maxNameCount];
|
||||
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
|
||||
|
||||
struct NodeStack {
|
||||
Uint32* next;
|
||||
Uint32* limit;
|
||||
Uint32 pushedList;
|
||||
};
|
||||
|
||||
// Allocate the node stack and initialize the node stack pointer.
|
||||
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
|
||||
NodeStack* nodeStackPtr = nodeStack;
|
||||
|
||||
// We start by the begin node.
|
||||
Uint32 startNode = 0;
|
||||
Uint32* next = &startNode;
|
||||
Uint32* limit = &startNode + 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (next == limit) {
|
||||
// If there are no more node in the sibling, we have to pop the current
|
||||
// frame from the stack and update the copyStats of the pushed nodes.
|
||||
//
|
||||
if (nodeStackPtr == nodeStack)
|
||||
// We are at the bottom of the stack and there are no more nodes
|
||||
// to look at. We are done !
|
||||
break;
|
||||
|
||||
--nodeStackPtr;
|
||||
// We are done with all the children of this node in the dominator tree.
|
||||
// We need to update the copy information of all the new names pushed
|
||||
// during the walk over this node.
|
||||
Uint32 pushedList = nodeStackPtr->pushedList;
|
||||
while (pushedList != 0) {
|
||||
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
|
||||
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
|
||||
pushedList = nextName;
|
||||
}
|
||||
|
||||
// restore the previous frame.
|
||||
next = nodeStackPtr->next;
|
||||
limit = nodeStackPtr->limit;
|
||||
} else {
|
||||
Uint32 currentNode = *next++;
|
||||
Uint32 pushedList = 0;
|
||||
|
||||
|
||||
// Initialize the sets.
|
||||
pushed.clear();
|
||||
destinationList.clear();
|
||||
|
||||
// STEP1:
|
||||
// Walk the instruction list and to replace all the instruction uses with their new name.
|
||||
// If the instruction is a phi node and its defined register is alive at the end of this
|
||||
// block then we push the defined register into the stack.
|
||||
//
|
||||
ControlNode& node = *nodes[currentNode];
|
||||
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
|
||||
if (currentLiveOut != NULL) {
|
||||
// This is a phi node and we have to push its defined name if it is live
|
||||
// at the end of the node. We only need to do this if the CFG has critical edges.
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
|
||||
if (currentLiveOut->test(name))
|
||||
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP2:
|
||||
// Look at this node's successors' phiNodes. We keep track of the number of time
|
||||
// a VR will be used by another copy instruction and insert each definition into the
|
||||
// destinationList. This is the only pass over this node's successors as we will
|
||||
// get all the information we need in the CopyData structures.
|
||||
//
|
||||
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
|
||||
Uint32 useIndex = successorEdgePtr->getIndex();
|
||||
ControlNode& successor = successorEdgePtr->getTarget();
|
||||
|
||||
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
|
||||
// as soon as we find an instruction which is not a phi node
|
||||
InstructionList& phiNodes = successor.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
|
||||
|
||||
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
|
||||
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
|
||||
|
||||
assert(source.isRegister() && destination.isRegister());
|
||||
|
||||
RegisterName sourceName = source.getRegisterName();
|
||||
RegisterName destinationName = destination.getRegisterName();
|
||||
|
||||
// Get the correct name for the source.
|
||||
if (copyStats[sourceName].newName != NULL)
|
||||
sourceName = copyStats[sourceName].newName->newName;
|
||||
|
||||
// Update the CopyData structures.
|
||||
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
|
||||
copyStats[destinationName].source = sourceName;
|
||||
copyStats[destinationName].classKind = destination.getRegisterClass();
|
||||
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
|
||||
copyStats[destinationName].sourceNameToUse = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = sourceName;
|
||||
copyStats[sourceName].useCount++;
|
||||
destinationList.set(destinationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STEP3:
|
||||
// Insert into the worklist only the destination registers that will be not used in
|
||||
// another copy instruction in this block.
|
||||
//
|
||||
assert(workList.getSize() == 0);
|
||||
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
|
||||
Uint32 dest = destinationList.get(d);
|
||||
if (copyStats[dest].useCount == 0)
|
||||
workList.set(dest);
|
||||
}
|
||||
|
||||
// STEP4:
|
||||
// Insert the copy instructions.
|
||||
//
|
||||
Uint32 destinationListSize = destinationList.getSize();
|
||||
InstructionList::iterator endOfTheNode = instructions.end();
|
||||
|
||||
// Find the right place to insert the copy instructions.
|
||||
if (destinationListSize != 0)
|
||||
while (instructions.get(endOfTheNode).getFlags() & ifControl)
|
||||
endOfTheNode = instructions.retreat(endOfTheNode);
|
||||
|
||||
while (destinationListSize != 0) {
|
||||
while(workList.getSize()) {
|
||||
RegisterName destinationName = RegisterName(workList.getOne());
|
||||
RegisterName sourceName = copyStats[destinationName].source;
|
||||
|
||||
workList.clear(destinationName);
|
||||
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
|
||||
// Lost copy problem.
|
||||
copyStats[destinationName].isLiveOut = false;
|
||||
|
||||
RegisterName sourceName = destinationName;
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].useCount = 0;
|
||||
|
||||
// We need to insert a copy to a temporary register to keep the
|
||||
// source register valid at the end of the node defining it.
|
||||
// This copy will be inserted right after the phi node defining it.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
|
||||
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
|
||||
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
}
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterClassKind classKind = copyStats[destinationName].classKind;
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
|
||||
if (destinationList.test(sourceName))
|
||||
workList.set(sourceName);
|
||||
destinationList.clear(destinationName);
|
||||
}
|
||||
|
||||
destinationListSize = destinationList.getSize();
|
||||
if (destinationListSize != 0) {
|
||||
RegisterName sourceName = RegisterName(destinationList.getOne());
|
||||
RegisterName destinationName;
|
||||
|
||||
if (!copyStats[sourceName].temporaryName) {
|
||||
// Cycle problem.
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
} else
|
||||
destinationName = copyStats[sourceName].temporaryName;
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
|
||||
workList.set(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
nodeStackPtr->pushedList = pushedList;
|
||||
nodeStackPtr->next = next;
|
||||
nodeStackPtr->limit = limit;
|
||||
++nodeStackPtr;
|
||||
next = dGraph.getSuccessorsBegin(currentNode);
|
||||
limit = dGraph.getSuccessorsEnd(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _PHI_NODE_REMOVER_H_
|
||||
@@ -1,155 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "PhiNodeRemover.h"
|
||||
#include "LiveRange.h"
|
||||
#include "Liveness.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
#include "Coalescing.h"
|
||||
#include "Spilling.h"
|
||||
#include "Coloring.h"
|
||||
#include "Splits.h"
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
class InstructionEmitter;
|
||||
|
||||
UT_DEFINE_LOG_MODULE(RegAlloc);
|
||||
|
||||
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
|
||||
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
|
||||
// some special code for the high word annotation.
|
||||
//
|
||||
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
|
||||
|
||||
// Perform some tests on the instruction graph.
|
||||
//
|
||||
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
|
||||
|
||||
// Replace the phi node instructions by their equivalent copy instructions.
|
||||
//
|
||||
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
|
||||
|
||||
// Do the register allocation.
|
||||
//
|
||||
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
|
||||
registerAllocator.doGraphColoring();
|
||||
}
|
||||
|
||||
void RegisterAllocator::doGraphColoring()
|
||||
{
|
||||
// Initialize the liverange map.
|
||||
//
|
||||
initLiveRanges();
|
||||
|
||||
// Build the live ranges. We do this to compress the number of RegisterNames
|
||||
// used in the insterference graph.
|
||||
//
|
||||
LiveRange<LowRegisterPressure>::build(*this);
|
||||
|
||||
// Remove unnecessary copies.
|
||||
//
|
||||
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
|
||||
|
||||
for (Uint8 loop = 0; loop < 10; loop++) {
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
|
||||
|
||||
while(true) {
|
||||
// Build the interference graph.
|
||||
//
|
||||
iGraph.build();
|
||||
|
||||
// Coalesce the copy instructions.
|
||||
//
|
||||
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the interference graph.
|
||||
//
|
||||
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Calculate the spill costs.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
|
||||
|
||||
// Calculate the split costs.
|
||||
//
|
||||
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
|
||||
|
||||
// Build the live range graph.
|
||||
//
|
||||
lGraph.build();
|
||||
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Color the graph. If it succeeds then we're done with the
|
||||
// register allocation.
|
||||
//
|
||||
if (Coloring<LowRegisterPressure>::color(*this)) {
|
||||
// Write the final colors in the instruction graph.
|
||||
//
|
||||
Coloring<LowRegisterPressure>::finalColoring(*this);
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to spill some registers.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::insertSpillCode(*this);
|
||||
|
||||
// Insert the split instructions.
|
||||
//
|
||||
Splits<LowRegisterPressure>::insertSplitCode(*this);
|
||||
|
||||
// Update the live ranges.
|
||||
//
|
||||
// FIX
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
RegisterAllocatorTools::updateInstructionGraph(*this);
|
||||
RegisterAllocatorTools::printInstructions(*this);
|
||||
#endif
|
||||
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void RegisterAllocator::initLiveRanges()
|
||||
{
|
||||
Uint32 count = this->nameCount;
|
||||
RegisterName* name2range = new(pool) RegisterName[nameCount];
|
||||
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
|
||||
name2range[r] = r;
|
||||
this->name2range = name2range;
|
||||
rangeCount = count;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_H_
|
||||
#define _REGISTER_ALLOCATOR_H_
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
struct SpillCost;
|
||||
struct SplitCost;
|
||||
|
||||
#include "Liveness.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h" // This should included by Backend.cpp
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
|
||||
//template <class RegisterPressure>
|
||||
class RegisterAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
Pool& pool; //
|
||||
ControlGraph& controlGraph; //
|
||||
VirtualRegisterManager& vrManager; //
|
||||
InstructionEmitter& emitter; //
|
||||
|
||||
RegisterName* name2range; //
|
||||
RegisterName* color; //
|
||||
SpillCost* spillCost; //
|
||||
SparseSet* willSpill; //
|
||||
SplitCost* splitCost; //
|
||||
NameLinkedList** splitAround; //
|
||||
InterferenceGraph<LowRegisterPressure> iGraph; //
|
||||
LiveRangeGraph<LowRegisterPressure> lGraph; //
|
||||
LivenessInfo<LowRegisterPressure> liveness; //
|
||||
Uint32 nameCount; //
|
||||
Uint32 rangeCount; //
|
||||
bool splitFound; //
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
//
|
||||
void doGraphColoring();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
|
||||
|
||||
//
|
||||
//
|
||||
void initLiveRanges();
|
||||
|
||||
//
|
||||
//
|
||||
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_H_
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
#ifdef DEBUG
|
||||
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
|
||||
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
|
||||
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
BitSet registerSeen(controlGraph.pool, nameCount);
|
||||
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
bool renameRegisters = false;
|
||||
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
|
||||
renameRegisters = true;
|
||||
fprintf(stderr,
|
||||
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
|
||||
" is never used nor defined by any instruction in the instruction graph\n"
|
||||
" PLEASE FIX \n",
|
||||
i);
|
||||
}
|
||||
if (renameRegisters) {
|
||||
Instruction** definingInstruction = new Instruction*[nameCount];
|
||||
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
|
||||
RegisterName* newName = new RegisterName[nameCount];
|
||||
memset(newName, '\0', nameCount * sizeof(RegisterName));
|
||||
RegisterName nextName = RegisterName(1);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vrManager.setSize(nextName);
|
||||
|
||||
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
|
||||
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
|
||||
for (Uint32 i = 1; i < nameCount; i++)
|
||||
if (newName[i] != 0)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
|
||||
else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
|
||||
|
||||
|
||||
delete newName;
|
||||
delete definingInstruction;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.advance(i);
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
|
||||
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
|
||||
|
||||
if (source == destination)
|
||||
instruction.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
|
||||
// Set the index of the incoming edges.
|
||||
Uint32 index = 0;
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
|
||||
predecessors.get(p).setIndex(index++);
|
||||
|
||||
// Insert the phi node instruction in the instruction list.
|
||||
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
PhiNode& phiNode = phiNodes.get(i);
|
||||
ValueKind kind = phiNode.getKind();
|
||||
|
||||
if (!isStorableKind(kind))
|
||||
continue;
|
||||
|
||||
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
|
||||
Uint32 nInputs = phiNode.nInputs();
|
||||
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
|
||||
if (isDoublewordKind(kind)) {
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
|
||||
if (cost[i].infinite)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SplitCost* cost = registerAllocator.splitCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
|
||||
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
|
||||
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
phiNodes.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
if (!instructions.empty())
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
|
||||
}
|
||||
|
||||
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
instructions.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
@@ -1,117 +0,0 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
#define _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
#include "RegisterTypes.h"
|
||||
#include <string.h>
|
||||
|
||||
class RegisterAllocator;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
struct RegisterAllocatorTools
|
||||
{
|
||||
//
|
||||
//
|
||||
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
|
||||
|
||||
#ifdef DEBUG
|
||||
//
|
||||
//
|
||||
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
static void printInstructions(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSpillCosts(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSplitCosts(RegisterAllocator& registerAllocator);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
//
|
||||
// FIX: this should go in a class (LookupTable ?)
|
||||
//
|
||||
|
||||
inline RegisterName findRoot(RegisterName name, RegisterName* table)
|
||||
{
|
||||
RegisterName* stack = table;
|
||||
RegisterName* stackPtr = stack;
|
||||
|
||||
RegisterName newName;
|
||||
while((newName = table[name]) != name) {
|
||||
*--stackPtr = name;
|
||||
name = newName;
|
||||
}
|
||||
|
||||
while (stackPtr != stack)
|
||||
table[*stackPtr++] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void init(RegisterName* table, Uint32 nameCount)
|
||||
{
|
||||
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
|
||||
table[r] = r;
|
||||
}
|
||||
|
||||
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
|
||||
{
|
||||
RegisterName* liveRange = new RegisterName[tableSize];
|
||||
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
|
||||
|
||||
// Update the lookup table.
|
||||
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
|
||||
findRoot(r, table);
|
||||
|
||||
// Count the liveranges.
|
||||
Uint32 liveRangeCount = 1;
|
||||
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
|
||||
if (table[s] == s)
|
||||
liveRange[s] = RegisterName(liveRangeCount++);
|
||||
|
||||
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
|
||||
name2range[t] = liveRange[table[name2range[t]]];
|
||||
|
||||
return liveRangeCount;
|
||||
}
|
||||
|
||||
inline double doLog10(Uint32 power)
|
||||
{
|
||||
double log = 1.0;
|
||||
while (power--)
|
||||
log *= 10.0;
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
@@ -1,25 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_CLASS_H_
|
||||
#define _REGISTER_CLASS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
#endif // _REGISTER_CLASS_H_
|
||||
@@ -1,104 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_TYPES_H_
|
||||
#define _REGISTER_TYPES_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterName -
|
||||
//
|
||||
|
||||
enum RegisterName {
|
||||
rnInvalid = 0,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterClassKind -
|
||||
//
|
||||
|
||||
enum RegisterClassKind {
|
||||
rckInvalid = 0,
|
||||
rckGeneral,
|
||||
rckStackSlot,
|
||||
|
||||
nRegisterClassKind
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterID -
|
||||
//
|
||||
|
||||
enum RegisterID {
|
||||
invalidID = 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterKind -
|
||||
//
|
||||
|
||||
enum RegisterKind {
|
||||
rkCallerSave = 0,
|
||||
rkCalleeSave,
|
||||
};
|
||||
|
||||
struct NameLinkedList {
|
||||
RegisterName name;
|
||||
NameLinkedList* next;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const registerNameMask = 0x03ffffff;
|
||||
const coloredRegisterMask = 0x04000000;
|
||||
const machineRegisterMask = 0x08000000;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const coloredRegisterShift = 26;
|
||||
const machineRegisterShift = 27;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
const registerNameMask = 0x0fffffff;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
|
||||
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
|
||||
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
|
||||
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
|
||||
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
|
||||
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
|
||||
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // _REGISTER_TYPES_H_
|
||||
@@ -1,32 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SSATools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
if (!controlGraph.hasBackEdges)
|
||||
return;
|
||||
|
||||
Liveness liveness(controlGraph.pool);
|
||||
liveness.buildLivenessAnalysis(controlGraph, vrManager);
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _SPARSE_SET_H_
|
||||
#define _SPARSE_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "LogModule.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
class SparseSet
|
||||
{
|
||||
private:
|
||||
|
||||
struct Node {
|
||||
Uint32 element;
|
||||
Uint32 stackIndex;
|
||||
};
|
||||
|
||||
Node* node;
|
||||
Uint32 count;
|
||||
Uint32 universeSize;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
SparseSet(const SparseSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
|
||||
|
||||
// Clear the sparse set.
|
||||
void clear() {count = 0;}
|
||||
// Clear the element at index.
|
||||
inline void clear(Uint32 index);
|
||||
// Set the element at index.
|
||||
inline void set(Uint32 index);
|
||||
// Return true if the element at index is set.
|
||||
inline bool test(Uint32 index) const;
|
||||
// Union with the given sparse set.
|
||||
inline void or(const SparseSet& set);
|
||||
// Intersection with the given sparse set.
|
||||
inline void and(const SparseSet& set);
|
||||
// Difference with the given sparse set.
|
||||
inline void difference(const SparseSet& set);
|
||||
// Copy set.
|
||||
inline SparseSet& operator = (const SparseSet& set);
|
||||
inline SparseSet& operator = (const BitSet& set);
|
||||
// Return true if the sparse sets are identical.
|
||||
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
|
||||
// Return true if the sparse sets are different.
|
||||
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
|
||||
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
|
||||
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return count - 1;}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return --pos;}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos < 0;}
|
||||
// Return the element for the given iterator;
|
||||
Uint32 get(iterator pos) const {return node[pos].element;}
|
||||
// Return one element of this set.
|
||||
Uint32 getOne() const {assert(count > 0); return node[0].element;}
|
||||
// Return the size of this set.
|
||||
Uint32 getSize() const {return count;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
inline void SparseSet::clear(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex < count) && (node[stackIndex].element == element)) {
|
||||
Uint32 stackTop = node[count - 1].element;
|
||||
|
||||
node[stackIndex].element = stackTop;
|
||||
node[stackTop].stackIndex = stackIndex;
|
||||
this->count = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SparseSet::set(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
|
||||
node[count].element = element;
|
||||
node[element].stackIndex = count;
|
||||
this->count = count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SparseSet::test(Uint32 element) const
|
||||
{
|
||||
checkMember(element);
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
return ((stackIndex < count) && (node[stackIndex].element == element));
|
||||
}
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const SparseSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Uint32 sourceCount = set.getSize();
|
||||
Node* node = this->node;
|
||||
|
||||
memcpy(node, set.node, sourceCount * sizeof(Node));
|
||||
|
||||
for (Uint32 i = 0; i < sourceCount; i++) {
|
||||
Uint32 element = node[i].element;
|
||||
node[element].stackIndex = i;
|
||||
}
|
||||
|
||||
count = sourceCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const BitSet& set)
|
||||
{
|
||||
// FIX: there's room for optimization here.
|
||||
assert(universeSize == set.getSize());
|
||||
|
||||
clear();
|
||||
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
|
||||
this->set(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _SPARSE_SET_H_
|
||||
@@ -1,270 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
#define INCLUDE_EMITTER
|
||||
#include "CpuInfo.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Spilling.h"
|
||||
|
||||
|
||||
void Spilling::
|
||||
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
||||
{
|
||||
PRUint32 nVirtualRegisters = vRegManager.count();
|
||||
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
||||
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
||||
RegisterFifo grNeedLoad(nVirtualRegisters);
|
||||
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
||||
|
||||
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
||||
{
|
||||
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
||||
ControlNode& node = *dfsList[n];
|
||||
|
||||
currentLive = node.liveAtEnd;
|
||||
|
||||
PRUint32 nGeneralAlive = 0;
|
||||
PRUint32 nFloatingPointAlive = 0;
|
||||
|
||||
// Get the number of registers alive at the end of this node.
|
||||
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
||||
if (vReg.spillInfo.willSpill)
|
||||
{
|
||||
currentLive.clear(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
||||
{
|
||||
Instruction& instruction = instructions.get(i);
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* defPtr;
|
||||
|
||||
// if(node.dfsNum == 8) { printf("\n");
|
||||
// instruction.printPretty(stdout);
|
||||
// printf("\n"); }
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
currentLive.clear(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive--;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for deaths
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
if (!currentLive.test(vReg.getRegisterIndex()))
|
||||
// This is the last use of this register.
|
||||
{
|
||||
currentLive.set(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = grNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nGeneralAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = fpNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nFloatingPointAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle uses
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
PRUint32 registerIndex = vReg.getRegisterIndex();
|
||||
|
||||
if (vReg.spillInfo.willSpill) {
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (!grNeedLoad.test(registerIndex))
|
||||
{
|
||||
grNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/* if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
if (!fpNeedLoad.test(registerIndex))
|
||||
{
|
||||
fpNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/*if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
usedInThisInstruction.set(registerIndex);
|
||||
vReg.spillInfo.lastUsingInstruction = &instruction;
|
||||
}
|
||||
currentLive.clear(registerIndex);
|
||||
} else { // will not spill
|
||||
currentLive.set(registerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
|
||||
if (vReg.spillInfo.willSpill)
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
||||
// this virtualRegister was used in this instruction and is also defined. We need to move
|
||||
// this virtual register to its alias first and then save it to memory.
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
||||
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = grNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
while (!fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = fpNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,269 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPILLING_H_
|
||||
#define _SPILLING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Spilling
|
||||
{
|
||||
private:
|
||||
static void insertStoreAfter(Instruction& instruction, RegisterName name);
|
||||
static void insertLoadBefore(Instruction& instruction, RegisterName name);
|
||||
|
||||
public:
|
||||
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
|
||||
static void insertSpillCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SpillCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
double copies;
|
||||
double cost;
|
||||
bool infinite;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
SparseSet& willSpill = *registerAllocator.willSpill;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
needLoad.clear();
|
||||
currentLive = liveOut[n];
|
||||
mustSpill = currentLive;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.retreat(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
bool foundLiveDefine = false;
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
if (defineBegin != defineEnd && !foundLiveDefine) {
|
||||
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
|
||||
instruction.remove();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
#ifdef DEBUG
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
|
||||
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (willSpill.test(range))
|
||||
insertStoreAfter(instruction, range);
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!currentLive.test(range))
|
||||
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
|
||||
RegisterName load = RegisterName(needLoad.get(r));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instruction, load);
|
||||
mustSpill.set(load);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
currentLive.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
RegisterName load = RegisterName(needLoad.get(l));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instructions.first(), load);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert load for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert store for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet live(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
|
||||
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
|
||||
|
||||
SpillCost* cost = new SpillCost[rangeCount];
|
||||
memset(cost, '\0', rangeCount * sizeof(SpillCost));
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
needLoad.clear();
|
||||
live = liveOut[n];
|
||||
mustSpill = live;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range))
|
||||
cost[range].infinite = true;
|
||||
|
||||
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
|
||||
cost[range].stores += weight;
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
if (!live.test(name2range[usePtr->getRegisterName()])) {
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
Uint32 range = needLoad.get(l);
|
||||
cost[range].loads += weight;
|
||||
mustSpill.set(range);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
|
||||
live.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[useBegin[0].getRegisterName()];
|
||||
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
|
||||
|
||||
cost[source].copies += weight;
|
||||
cost[destination].copies += weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
|
||||
cost[needLoad.get(s)].loads += weight;
|
||||
}
|
||||
|
||||
for (Uint32 r = 0; r < rangeCount; r++) {
|
||||
SpillCost& c = cost[r];
|
||||
c.cost = 2 * (c.loads + c.stores) - c.copies;
|
||||
}
|
||||
|
||||
registerAllocator.spillCost = cost;
|
||||
}
|
||||
|
||||
#endif // _SPILLING_H_
|
||||
@@ -1,239 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SPLITS_H_
|
||||
#define _SPLITS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Splits
|
||||
{
|
||||
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
|
||||
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
|
||||
static void insertSplitCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SplitCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
|
||||
{
|
||||
// FIX
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
|
||||
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
|
||||
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >=0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
RegisterName c = color[neighbor];
|
||||
|
||||
if (c < 6) { // FIX
|
||||
NameLinkedList* node = new(pool) NameLinkedList();
|
||||
node->name = neighbor;
|
||||
node->next = neighborsWithColor[c];
|
||||
neighborsWithColor[c] = node;
|
||||
}
|
||||
}
|
||||
|
||||
bool splitAroundName = true;
|
||||
|
||||
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
|
||||
RegisterName bestColor = RegisterName(6); // FIX
|
||||
double bestCost = registerAllocator.spillCost[range].cost;
|
||||
SplitCost* splitCost = registerAllocator.splitCost;
|
||||
|
||||
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
|
||||
|
||||
double splitAroundNameCost = 0.0;
|
||||
bool canSplitAroundName = true;
|
||||
|
||||
SplitCost& sCost = splitCost[range];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(neighbor, range)) {
|
||||
canSplitAroundName = false;
|
||||
break;
|
||||
} else
|
||||
splitAroundNameCost += addedCost;
|
||||
}
|
||||
if (canSplitAroundName && splitAroundNameCost < bestCost) {
|
||||
bestCost = splitAroundNameCost;
|
||||
bestColor = i;
|
||||
splitAroundName = true;
|
||||
}
|
||||
|
||||
double splitAroundColorCost = 0.0;
|
||||
bool canSplitAroundColor = true;
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(range, neighbor)) {
|
||||
canSplitAroundColor = false;
|
||||
break;
|
||||
} else {
|
||||
SplitCost& sCost = splitCost[neighbor];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
splitAroundColorCost += addedCost;
|
||||
}
|
||||
}
|
||||
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
|
||||
bestCost = splitAroundColorCost;
|
||||
bestColor = i;
|
||||
splitAroundName = false;
|
||||
}
|
||||
}
|
||||
if (bestColor < RegisterName(6)) {
|
||||
color[range] = bestColor;
|
||||
registerAllocator.splitFound = true;
|
||||
|
||||
NameLinkedList** splitAround = registerAllocator.splitAround;
|
||||
|
||||
if (splitAroundName)
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
newNode->name = node->name;
|
||||
newNode->next = splitAround[range];
|
||||
splitAround[range] = newNode;
|
||||
}
|
||||
else
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
RegisterName neighbor = node->name;
|
||||
newNode->name = range;
|
||||
newNode->next = splitAround[neighbor];
|
||||
splitAround[neighbor] = newNode;
|
||||
}
|
||||
|
||||
trespass("Found a split");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
|
||||
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
|
||||
|
||||
SparseSet live(pool, rangeCount);
|
||||
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
live = liveOut[n];
|
||||
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
|
||||
ControlNode& successor = successorsPtr->getTarget();
|
||||
|
||||
if (successor.getControlKind() != ckEnd) {
|
||||
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
|
||||
|
||||
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
|
||||
RegisterName name = RegisterName(live.get(i));
|
||||
if (!successorLiveIn.test(name))
|
||||
splitCost[name].loads += doLog10(successor.loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!live.test(range)) {
|
||||
if (&instruction != &instructions.last())
|
||||
splitCost[range].loads += weight;
|
||||
else {
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
|
||||
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
live.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
|
||||
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
|
||||
registerAllocator.splitAround = splitAround;
|
||||
|
||||
registerAllocator.splitCost = splitCost;
|
||||
registerAllocator.splitFound = false;
|
||||
}
|
||||
|
||||
#endif // _SPLITS_H_
|
||||
@@ -1,186 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "Timer.h"
|
||||
#include "Pool.h"
|
||||
|
||||
static Pool pool; // Pool for the Timer class.
|
||||
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
|
||||
|
||||
const nTimersInABlock = 128; // Number of timers in a block.
|
||||
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
|
||||
static Uint8 nextTimer = 0; // nextAvailableTimer.
|
||||
|
||||
//
|
||||
// Calibrate the call to PR_Now().
|
||||
//
|
||||
static PRTime calibrate()
|
||||
{
|
||||
PRTime t = PR_Now();
|
||||
PRTime& a = *new(pool) PRTime();
|
||||
|
||||
// Call 10 times the PR_Now() function.
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
t = (PR_Now() - t + 9) / 10;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static PRTime adjust = calibrate();
|
||||
|
||||
//
|
||||
// Return the named timer..
|
||||
//
|
||||
TimerEntry& Timer::getTimerEntry(const char* name)
|
||||
{
|
||||
if (!timerEntries.exists(name)) {
|
||||
TimerEntry* newEntry = new(pool) TimerEntry();
|
||||
newEntry->accumulator = 0;
|
||||
newEntry->running = false;
|
||||
timerEntries.add(name, newEntry);
|
||||
}
|
||||
|
||||
return *timerEntries[name];
|
||||
}
|
||||
|
||||
//
|
||||
// Return a reference to a new timer.
|
||||
//
|
||||
PRTime& Timer::getNewTimer()
|
||||
{
|
||||
if (nextTimer >= nTimersInABlock) {
|
||||
timers = new(pool) PRTime[nTimersInABlock];
|
||||
nextTimer = 0;
|
||||
}
|
||||
return timers[nextTimer++];
|
||||
}
|
||||
|
||||
static Uint32 timersAreFrozen = 0;
|
||||
|
||||
//
|
||||
// Start the named timer.
|
||||
//
|
||||
void Timer::start(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(!timer.running);
|
||||
|
||||
timer.accumulator = 0;
|
||||
timer.running = true;
|
||||
timer.done = false;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the named timer.
|
||||
//
|
||||
void Timer::stop(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(timer.running);
|
||||
timer.running = false;
|
||||
timer.done = true;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeze all the running timers.
|
||||
//
|
||||
void Timer::freezeTimers()
|
||||
{
|
||||
PRTime when = PR_Now() - adjust;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry*> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.accumulator += (when - *entry.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
timersAreFrozen++;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfreeze all the running timers.
|
||||
//
|
||||
void Timer::unfreezeTimers()
|
||||
{
|
||||
PR_ASSERT(timersAreFrozen != 0);
|
||||
timersAreFrozen--;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry *> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
PRTime& newStart = getNewTimer();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.startTime = &newStart;
|
||||
}
|
||||
}
|
||||
|
||||
newStart = PR_Now();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print the named timer in the file f.
|
||||
//
|
||||
void Timer::print(FILE* f, const char *name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
|
||||
PR_ASSERT(timer.done);
|
||||
PRTime elapsed = timer.accumulator;
|
||||
|
||||
if (elapsed >> 32) {
|
||||
fprintf(f, "[timer %s out of range]\n", name);
|
||||
} else {
|
||||
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
|
||||
}
|
||||
fflush(f);
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "prtime.h"
|
||||
|
||||
//
|
||||
// Naming convention:
|
||||
// As the class Timer contains only static methods, the timer's name should start with the
|
||||
// module name. Otherwise starting 2 timers with the same name will assert.
|
||||
//
|
||||
|
||||
#ifndef NO_TIMER
|
||||
|
||||
struct TimerEntry
|
||||
{
|
||||
PRTime *startTime; // Current time when we start the timer.
|
||||
PRTime accumulator; // Time spent in this timer.
|
||||
bool running; // True if the timer is running.
|
||||
bool done; // True if the timer was running and was stopped.
|
||||
};
|
||||
|
||||
class Timer
|
||||
{
|
||||
private:
|
||||
|
||||
// Return the named timer.
|
||||
static TimerEntry& getTimerEntry(const char* name);
|
||||
// Return a reference to a new Timer.
|
||||
static PRTime& getNewTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Start the timer.
|
||||
static void start(const char* name);
|
||||
// Stop the timer.
|
||||
static void stop(const char* name);
|
||||
// Freeze all the running timers.
|
||||
static void freezeTimers();
|
||||
// Unfreeze all the running timers.
|
||||
static void unfreezeTimers();
|
||||
// Print the timer.
|
||||
static void print(FILE* f, const char *name);
|
||||
};
|
||||
|
||||
inline void startTimer(const char* name) {Timer::start(name);}
|
||||
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
|
||||
#define START_TIMER_SAFE Timer::freezeTimers();
|
||||
#define END_TIMER_SAFE Timer::unfreezeTimers();
|
||||
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
|
||||
|
||||
#else /* NO_TIMER */
|
||||
|
||||
inline void startTimer(const char* /*name*/) {}
|
||||
inline void stopTimer(const char* /*name*/) {}
|
||||
#define START_TIMER_SAFE
|
||||
#define END_TIMER_SAFE
|
||||
#define TIMER_SAFE(x) x;
|
||||
|
||||
#endif /* NO_TIMER */
|
||||
#endif /* _TIMER_H_ */
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _VIRTUAL_REGISTER_H_
|
||||
#define _VIRTUAL_REGISTER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "IndexedPool.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "RegisterTypes.h"
|
||||
#include "RegisterClass.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister - 24b
|
||||
|
||||
class Instruction;
|
||||
|
||||
class VirtualRegister : public IndexedObject<VirtualRegister>
|
||||
{
|
||||
public:
|
||||
|
||||
Instruction* definingInstruction; // Instruction defining this VR.
|
||||
|
||||
// Initialize a VR of the given classKind.
|
||||
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
|
||||
|
||||
// Return the defining instruction for this VR.
|
||||
Instruction* getDefiningInstruction() const {return definingInstruction;}
|
||||
// Set the defining instruction.
|
||||
void setDefiningInstruction(Instruction& insn);
|
||||
};
|
||||
|
||||
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
|
||||
// they have the same index. If they have the same index then they are at the same
|
||||
// address in the indexed pool.
|
||||
//
|
||||
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
29
mozilla/rdf/Makefile.in
Normal file
29
mozilla/rdf/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = base content datasource build
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
29
mozilla/rdf/base/Makefile.in
Normal file
29
mozilla/rdf/base/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
27
mozilla/rdf/base/makefile.win
Normal file
27
mozilla/rdf/base/makefile.win
Normal file
@@ -0,0 +1,27 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
DIRS=\
|
||||
public \
|
||||
src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
11
mozilla/rdf/base/public/MANIFEST
Normal file
11
mozilla/rdf/base/public/MANIFEST
Normal file
@@ -0,0 +1,11 @@
|
||||
rdf.h
|
||||
nsIRDFCompositeDataSource.h
|
||||
nsIRDFContentSink.h
|
||||
nsIRDFCursor.h
|
||||
nsIRDFDataSource.h
|
||||
nsIRDFNode.h
|
||||
nsIRDFObserver.h
|
||||
nsIRDFResourceFactory.h
|
||||
nsIRDFService.h
|
||||
nsIRDFXMLDataSource.h
|
||||
nsIRDFXMLSource.h
|
||||
45
mozilla/rdf/base/public/Makefile.in
Normal file
45
mozilla/rdf/base/public/Makefile.in
Normal file
@@ -0,0 +1,45 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
EXPORTS = \
|
||||
rdf.h \
|
||||
nsIRDFCompositeDataSource.h \
|
||||
nsIRDFContentSink.h \
|
||||
nsIRDFCursor.h \
|
||||
nsIRDFDataSource.h \
|
||||
nsIRDFNode.h \
|
||||
nsIRDFObserver.h \
|
||||
nsIRDFResourceFactory.h \
|
||||
nsIRDFService.h \
|
||||
nsIRDFXMLDataSource.h \
|
||||
nsIRDFXMLSource.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
39
mozilla/rdf/base/public/makefile.win
Normal file
39
mozilla/rdf/base/public/makefile.win
Normal file
@@ -0,0 +1,39 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
|
||||
MODULE=rdf
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
EXPORTS=\
|
||||
rdf.h \
|
||||
nsIRDFCompositeDataSource.h \
|
||||
nsIRDFContentSink.h \
|
||||
nsIRDFCursor.h \
|
||||
nsIRDFDataSource.h \
|
||||
nsIRDFNode.h \
|
||||
nsIRDFObserver.h \
|
||||
nsIRDFResourceFactory.h \
|
||||
nsIRDFService.h \
|
||||
nsIRDFXMLDataSource.h \
|
||||
nsIRDFXMLSource.h \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
58
mozilla/rdf/base/public/nsIRDFCompositeDataSource.h
Normal file
58
mozilla/rdf/base/public/nsIRDFCompositeDataSource.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
RDF composite data source interface. A composite data source
|
||||
aggregates individual RDF data sources.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFCompositeDataSource_h__
|
||||
#define nsIRDFCompositeDataSource_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
|
||||
class nsIRDFDataSource;
|
||||
|
||||
// 96343820-307c-11d2-bc15-00805f912fe7
|
||||
#define NS_IRDFCOMPOSITEDATASOURCE_IID \
|
||||
{ 0x96343820, 0x307c, 0x11d2, { 0xb, 0x15, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
|
||||
|
||||
/**
|
||||
* An <tt>nsIRDFCompositeDataSource</tt> composes individual data sources, providing
|
||||
* the illusion of a single, coherent RDF graph.
|
||||
*/
|
||||
class nsIRDFCompositeDataSource : public nsIRDFDataSource {
|
||||
public:
|
||||
/**
|
||||
* Add a datasource the the database.
|
||||
*/
|
||||
NS_IMETHOD AddDataSource(nsIRDFDataSource* source) = 0;
|
||||
|
||||
/**
|
||||
* Remove a datasource from the database
|
||||
*/
|
||||
NS_IMETHOD RemoveDataSource(nsIRDFDataSource* source) = 0;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result);
|
||||
|
||||
#endif /* nsIRDFCompositeDataSource_h__ */
|
||||
71
mozilla/rdf/base/public/nsIRDFContentSink.h
Normal file
71
mozilla/rdf/base/public/nsIRDFContentSink.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An RDF-specific content sink. The content sink is targeted by the
|
||||
parser for building the RDF content model.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFContentSink_h___
|
||||
#define nsIRDFContentSink_h___
|
||||
|
||||
#include "nsIXMLContentSink.h"
|
||||
class nsIDocument;
|
||||
class nsIRDFXMLDataSource;
|
||||
class nsINameSpaceManager;
|
||||
class nsIURL;
|
||||
|
||||
// {751843E2-8309-11d2-8EAC-00805F29F370}
|
||||
#define NS_IRDFCONTENTSINK_IID \
|
||||
{ 0x751843e2, 0x8309, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
/**
|
||||
* This interface represents a content sink for RDF files.
|
||||
*/
|
||||
|
||||
class nsIRDFContentSink : public nsIXMLContentSink {
|
||||
public:
|
||||
/**
|
||||
* Initialize the content sink.
|
||||
*/
|
||||
NS_IMETHOD Init(nsIURL* aURL, nsINameSpaceManager* aNameSpaceManager) = 0;
|
||||
|
||||
/**
|
||||
* Set the content sink's RDF Data source
|
||||
*/
|
||||
NS_IMETHOD SetDataSource(nsIRDFXMLDataSource* aDataSource) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the content sink's RDF data source.
|
||||
*/
|
||||
NS_IMETHOD GetDataSource(nsIRDFXMLDataSource*& rDataSource) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This constructs a content sink that can be used without a
|
||||
* document, say, to create a stand-alone in-memory graph.
|
||||
*/
|
||||
nsresult
|
||||
NS_NewRDFContentSink(nsIRDFContentSink** aResult);
|
||||
|
||||
|
||||
#endif // nsIRDFContentSink_h___
|
||||
167
mozilla/rdf/base/public/nsIRDFCursor.h
Normal file
167
mozilla/rdf/base/public/nsIRDFCursor.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Interfaces for RDF cursors, including nsIRDFCursor,
|
||||
nsIRDFAssertionCursor, nsIRDFArcsInCursor, and nsIRDFArcsOutCursor.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFCursor_h__
|
||||
#define nsIRDFCursor_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "prtypes.h"
|
||||
#include "rdf.h" // for error codes
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFNode;
|
||||
class nsIRDFResource;
|
||||
|
||||
// 1c2abdb0-4cef-11d2-bc16-00805f912fe7
|
||||
#define NS_IRDFCURSOR_IID \
|
||||
{ 0x1c2abdb0, 0x4cef, 0x11d2, { 0xbc, 0x16, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
|
||||
|
||||
/**
|
||||
* An abstract base interface that is the basis for all RDF cursors.
|
||||
*/
|
||||
class nsIRDFCursor : public nsISupports {
|
||||
public:
|
||||
/**
|
||||
* Advance the cursor to the next element.
|
||||
* @return NS_ERROR_RDF_CURSOR_EMPTY if the cursor has reached the end
|
||||
* and there are no more elements to enumerate; otherwise, NS_OK
|
||||
* unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD Advance(void) = 0;
|
||||
/* Retrieve the data source from which the current item was obtained.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) = 0;
|
||||
/**
|
||||
* Irrespective of the query, a cursor is an interator over a set.
|
||||
* This allows you to obtain the current value.
|
||||
*/
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// {1ED57100-9904-11d2-8EBA-00805F29F370}
|
||||
#define NS_IRDFASSERTIONCURSOR_IID \
|
||||
{ 0x1ed57100, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
/**
|
||||
* A cursor that enumerates assertions
|
||||
* @seealso nsIRDFDataSource::GetTargetS(), nsIRDFDataSource::GetSources()
|
||||
*/
|
||||
class nsIRDFAssertionCursor : public nsIRDFCursor {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Retrieve the assertion's subject resource.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aSubject) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the assertion's predicate resource.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the assertion's object node.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aObject) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the assertion's truth value.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
|
||||
};
|
||||
|
||||
|
||||
// {1ED57101-9904-11d2-8EBA-00805F29F370}
|
||||
#define NS_IRDFARCSOUTCURSOR_IID \
|
||||
{ 0x1ed57101, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
/**
|
||||
* A cursor that enumerates the outbound arcs from a resource node.
|
||||
* @seealso nsIRDFDataSource::ArcsOut()
|
||||
*/
|
||||
class nsIRDFArcsOutCursor : public nsIRDFCursor {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the "subject" node from which the arcs originate.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aSubject) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the predicate label of the arc.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
|
||||
/**
|
||||
* Retrieve the truth value of the arc.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
* xxx rvg --- truth value doesn't make sense here.
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
// {1ED57102-9904-11d2-8EBA-00805F29F370}
|
||||
#define NS_IRDFARCSINCURSOR_IID \
|
||||
{ 0x1ed57102, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
/**
|
||||
* A cursor that enumerates the inbound arcs to a node.
|
||||
* @seealso nsIRDFDataSource::ArcsIn()
|
||||
*/
|
||||
class nsIRDFArcsInCursor : public nsIRDFCursor {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Retrieve the "object" node in which the arc terminates.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aObject) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the predicate label of the arc
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
|
||||
/**
|
||||
* Retrieve the truth value of the arc.
|
||||
* @return NS_OK, unless a catastrophic error occurs.
|
||||
* xxx rvg --- truth value doesn't make sense here.
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsIRDFCursor_h__ */
|
||||
201
mozilla/rdf/base/public/nsIRDFDataSource.h
Normal file
201
mozilla/rdf/base/public/nsIRDFDataSource.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The RDF data source interface. An RDF data source presents a
|
||||
graph-like interface to a back-end service.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFDataSource_h__
|
||||
#define nsIRDFDataSource_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
// {0F78DA58-8321-11d2-8EAC-00805F29F370}
|
||||
#define NS_IRDFDATASOURCE_IID \
|
||||
{ 0xf78da58, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
class nsIRDFAssertionCursor;
|
||||
class nsIRDFArcsInCursor;
|
||||
class nsIRDFArcsOutCursor;
|
||||
class nsIRDFDataBase;
|
||||
class nsIRDFNode;
|
||||
class nsIRDFObserver;
|
||||
class nsIRDFResource;
|
||||
|
||||
/**
|
||||
* An RDF data source.
|
||||
*/
|
||||
|
||||
class nsIRDFDataSource : public nsISupports {
|
||||
public:
|
||||
// XXX I didn't make some of these methods "const" because it's
|
||||
// probably pretty likely that many data sources will just make
|
||||
// stuff up at runtime to answer queries.
|
||||
|
||||
/**
|
||||
* Specify the URI for the data source: this is the prefix
|
||||
* that will be used to register the data source in the
|
||||
* data source registry.
|
||||
*/
|
||||
NS_IMETHOD Init(const char* uri) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the URI of the data source.
|
||||
*/
|
||||
NS_IMETHOD GetURI(const char* *uri) const = 0;
|
||||
|
||||
/**
|
||||
* Find an RDF resource that points to a given node over the
|
||||
* specified arc & truth value
|
||||
*
|
||||
* @return NS_ERROR_FAILURE if there is no source that leads
|
||||
* to the target with the specified property.
|
||||
*/
|
||||
NS_IMETHOD GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Find all RDF resources that point to a given node over the
|
||||
* specified arc & truth value
|
||||
*
|
||||
* @return NS_OK unless a catastrophic error occurs. If the
|
||||
* method returns NS_OK, you may assume that nsIRDFCursor points
|
||||
* to a valid (but possibly empty) cursor.
|
||||
*/
|
||||
NS_IMETHOD GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** sources /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Find a child of that is related to the source by the given arc
|
||||
* arc and truth value
|
||||
*
|
||||
* @return NS_ERROR_FAILURE if there is no target accessable from the
|
||||
* source via the specified property.
|
||||
*/
|
||||
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Find all children of that are related to the source by the given arc
|
||||
* arc and truth value.
|
||||
*
|
||||
* @return NS_OK unless a catastrophic error occurs. If the
|
||||
* method returns NS_OK, you may assume that nsIRDFCursor points
|
||||
* to a valid (but possibly empty) cursor.
|
||||
*/
|
||||
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** targets /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Add an assertion to the graph.
|
||||
*/
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv) = 0;
|
||||
|
||||
/**
|
||||
* Remove an assertion from the graph.
|
||||
*/
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target) = 0;
|
||||
|
||||
/**
|
||||
* Query whether an assertion exists in this graph.
|
||||
*
|
||||
* @return NS_OK unless a catastrophic error occurs.
|
||||
*/
|
||||
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Add an observer to this data source.
|
||||
*/
|
||||
NS_IMETHOD AddObserver(nsIRDFObserver* n) = 0;
|
||||
|
||||
/**
|
||||
* Remove an observer from this data source
|
||||
*/
|
||||
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) = 0;
|
||||
|
||||
// XXX individual resource observers?
|
||||
|
||||
/**
|
||||
* Get a cursor to iterate over all the arcs that point into a node.
|
||||
*
|
||||
* @return NS_OK unless a catastrophic error occurs. If the method
|
||||
* returns NS_OK, you may assume that labels points to a valid (but
|
||||
* possible empty) nsIRDFCursor object.
|
||||
*/
|
||||
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Get a cursor to iterate over all the arcs that originate in
|
||||
* a resource.
|
||||
*
|
||||
* @return NS_OK unless a catastrophic error occurs. If the method
|
||||
* returns NS_OK, you may assume that labels points to a valid (but
|
||||
* possible empty) nsIRDFCursor object.
|
||||
*/
|
||||
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels /* out */) = 0;
|
||||
|
||||
/**
|
||||
* Request that a data source write it's contents out to
|
||||
* permanent storage if applicable.
|
||||
*/
|
||||
NS_IMETHOD Flush() = 0;
|
||||
|
||||
/**
|
||||
* Determine whether the specified command is enabled for the
|
||||
* resource.
|
||||
*
|
||||
* XXX We will probably need to make this interface much more intricate
|
||||
* to handle arbitrary arguments and selection sets.
|
||||
*/
|
||||
NS_IMETHOD IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult) = 0;
|
||||
|
||||
/**
|
||||
* Perform the specified command on the resource.
|
||||
*
|
||||
* XXX We will probably need to make this interface much more intricate
|
||||
* to handle arbitrary arguments and selection sets.
|
||||
*/
|
||||
NS_IMETHOD DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget) = 0;
|
||||
};
|
||||
|
||||
#endif /* nsIRDFDataSource_h__ */
|
||||
104
mozilla/rdf/base/public/nsIRDFNode.h
Normal file
104
mozilla/rdf/base/public/nsIRDFNode.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
RDF node interfaces, including nsIRDFNode, nsIRDFResource, and
|
||||
nsIRDFLiteral. Nodes are the elements that appear in RDF graphs.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFNode_h__
|
||||
#define nsIRDFNode_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
// {0F78DA50-8321-11d2-8EAC-00805F29F370}
|
||||
#define NS_IRDFNODE_IID \
|
||||
{ 0xf78da50, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
/**
|
||||
*
|
||||
* Nodes are created using an instance of nsIRDFService, which
|
||||
* should be obtained from the service manager:
|
||||
*
|
||||
* nsIRDFService* service;
|
||||
* if (NS_SUCCEEDED(nsServiceManager::GetService(kCRDFServiceCID,
|
||||
* kIRDFServiceIID,
|
||||
* (nsISupports**) &service))) {
|
||||
* nsIRDFNode* node;
|
||||
* if (NS_SUCCEEDED(service->GetResource("http://foo.bar/", node))) {
|
||||
* // do something useful here...
|
||||
* NS_IF_RELEASE(node);
|
||||
* }
|
||||
* nsServiceManager::ReleaseService(kCRDFServiceCID, mgr);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
class nsIRDFNode : public nsISupports {
|
||||
public:
|
||||
/**
|
||||
* Determine if two nodes are identical
|
||||
*/
|
||||
NS_IMETHOD EqualsNode(nsIRDFNode* that, PRBool* result) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A resource node, which has unique object identity.
|
||||
*/
|
||||
class nsIRDFResource : public nsIRDFNode {
|
||||
public:
|
||||
/**
|
||||
* Get the 8-bit string value of the node.
|
||||
*/
|
||||
NS_IMETHOD GetValue(const char* *uri) const = 0;
|
||||
|
||||
/**
|
||||
* Determine if two resources are identical.
|
||||
*/
|
||||
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const = 0;
|
||||
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const = 0;
|
||||
};
|
||||
|
||||
// {E0C493D1-9542-11d2-8EB8-00805F29F370}
|
||||
#define NS_IRDFRESOURCE_IID \
|
||||
{ 0xe0c493d1, 0x9542, 0x11d2, { 0x8e, 0xb8, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
class nsIRDFLiteral : public nsIRDFNode {
|
||||
public:
|
||||
/**
|
||||
* Get the Unicode string value of the node.
|
||||
*/
|
||||
NS_IMETHOD GetValue(const PRUnichar* *value) const = 0;
|
||||
|
||||
/**
|
||||
* Determine if two resources are identical.
|
||||
*/
|
||||
NS_IMETHOD EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const = 0;
|
||||
};
|
||||
|
||||
// {E0C493D2-9542-11d2-8EB8-00805F29F370}
|
||||
#define NS_IRDFLITERAL_IID \
|
||||
{ 0xe0c493d2, 0x9542, 0x11d2, { 0x8e, 0xb8, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
#endif // nsIRDFNode_h__
|
||||
61
mozilla/rdf/base/public/nsIRDFObserver.h
Normal file
61
mozilla/rdf/base/public/nsIRDFObserver.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The RDF data source observer interface. Data source observers are
|
||||
notified when the contents of the graph change.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFObserver_h__
|
||||
#define nsIRDFObserver_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFResource;
|
||||
class nsIRDFNode;
|
||||
|
||||
/**
|
||||
* An observer on an nsIRDFDataSource.
|
||||
*/
|
||||
class nsIRDFObserver : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Called whenever a new assertion is made in the data source.
|
||||
*/
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object) = 0;
|
||||
|
||||
/**
|
||||
* Called whenever an assertion is removed from the data source.
|
||||
*/
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object) = 0;
|
||||
};
|
||||
|
||||
|
||||
// 3cc75360-484a-11d2-bc16-00805f912fe7
|
||||
#define NS_IRDFOBSERVER_IID \
|
||||
{ 0x3cc75360, 0x484a, 0x11d2, { 0xbc, 0x16, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
|
||||
|
||||
#endif /* nsIRDFObserver_h__ */
|
||||
72
mozilla/rdf/base/public/nsIRDFResourceFactory.h
Normal file
72
mozilla/rdf/base/public/nsIRDFResourceFactory.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
The RDF resource factory interface. A resource factory produces
|
||||
nsIRDFResource objects for a specified URI prefix.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFResourceFactory_h__
|
||||
#define nsIRDFResourceFactory_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
class nsIRDFResource;
|
||||
|
||||
// {8CE57A20-A02C-11d2-8EBF-00805F29F370}
|
||||
#define NS_IRDFRESOURCEFACTORY_IID \
|
||||
{ 0x8ce57a20, 0xa02c, 0x11d2, { 0x8e, 0xbf, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
/**
|
||||
* A resource factory can be registered with <tt>nsIRDFService</tt> to produce
|
||||
* resources with a certain <i>URI prefix</i>. The resource factory will be called
|
||||
* upon to create a new resource, which the resource manager will cache.
|
||||
*
|
||||
* @see nsIRDFService::RegisterResourceFactory
|
||||
* @see nsIRDFService::UnRegisterResourceFactory
|
||||
*/
|
||||
class nsIRDFResourceFactory : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method is called by the RDF service to create a new
|
||||
* resource.
|
||||
*
|
||||
* NOTE. After constructing a new resource via a call to
|
||||
* nsIRDFResourceFactory::CreateResource(), the implementation of
|
||||
* the RDF service calls nsIRDFResource::GetValue() on the
|
||||
* resulting resource. The resulting <tt>const char*</tt> is used
|
||||
* as a key for the resource cache. (The assumption is that the
|
||||
* custom resource implementation needs to store this information,
|
||||
* anyway.)
|
||||
*
|
||||
* This has important implications for a custom resource's
|
||||
* destructor; namely, that you must call
|
||||
* nsIRDFService::UnCacheResource() <b>before</b> releasing the
|
||||
* storage for the resource's URI. See
|
||||
* nsIRDFService::UnCacheResource() for more information.
|
||||
*/
|
||||
NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsIRDFResourceFactory_h__
|
||||
|
||||
174
mozilla/rdf/base/public/nsIRDFService.h
Normal file
174
mozilla/rdf/base/public/nsIRDFService.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The RDF service interface. This is a singleton object, and should be
|
||||
obtained from the <tt>nsServiceManager</tt>.
|
||||
|
||||
XXX I'm not particularly happy with the current APIs for named data
|
||||
sources. The idea is that you want "rdf:bookmarks" to always map to
|
||||
the "bookmarks" data store. The thing that bothers me now is that
|
||||
the implementation has to pre-load all of the data sources: that
|
||||
means you need to parse the bookmarks file, read the history, etc.,
|
||||
rather than doing this on-demand. With a little thought, it may be
|
||||
able to enormously improve these APIs so that pre-loading data
|
||||
sources is unnecessary.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFService_h__
|
||||
#define nsIRDFService_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
class nsIRDFDataBase;
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFLiteral;
|
||||
class nsIRDFResource;
|
||||
class nsIRDFResourceFactory;
|
||||
|
||||
typedef nsresult (*NSDataSourceConstructorCallback)(nsIRDFDataSource** aResult);
|
||||
|
||||
class nsIRDFService : public nsISupports {
|
||||
public:
|
||||
|
||||
// Resource management routines
|
||||
|
||||
/**
|
||||
* Construct an RDF resource from a single-byte URI. <tt>nsIRDFSerivce</tt>
|
||||
* caches resources that are in-use, so multiple calls to <tt>GetResource()</tt>
|
||||
* for the same <tt>uri</tt> will return identical pointers.
|
||||
*/
|
||||
NS_IMETHOD GetResource(const char* uri, nsIRDFResource** resource) = 0;
|
||||
|
||||
/**
|
||||
* Construct an RDF resource from a Unicode URI. This is provided
|
||||
* as a convenience method, allowing automatic, in-line C++
|
||||
* conversion from <tt>nsString</tt> objects. The <tt>uri</tt> will
|
||||
* be converted to a single-byte representation internally.
|
||||
*/
|
||||
NS_IMETHOD GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource) = 0;
|
||||
|
||||
/**
|
||||
* Construct an RDF literal from a Unicode string.
|
||||
*/
|
||||
NS_IMETHOD GetLiteral(const PRUnichar* value, nsIRDFLiteral** literal) = 0;
|
||||
|
||||
/**
|
||||
* Called to notify the resource manager that a resource is no
|
||||
* longer in use. This method should only be called from the
|
||||
* destructor of a "custom" resource implementation to notify the
|
||||
* RDF service that the last reference to the resource has been
|
||||
* released, so the resource is no longer valid.
|
||||
*
|
||||
* NOTE. As mentioned in nsIRDFResourceFactory::CreateResource(),
|
||||
* the RDF service will use the result of
|
||||
* nsIRDFResource::GetValue() as a key into its cache. For this
|
||||
* reason, you must always un-cache the resource <b>before</b>
|
||||
* releasing the storage for the <tt>const char*</tt> URI.
|
||||
*/
|
||||
NS_IMETHOD UnCacheResource(nsIRDFResource* resource) = 0;
|
||||
|
||||
/**
|
||||
* Registers the specified resource factory as the producer for resources that
|
||||
* have the specified <i>URI prefix</i>.
|
||||
*/
|
||||
NS_IMETHOD RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory) = 0;
|
||||
|
||||
/**
|
||||
* Unregsters the specified resource factory from producing resources that have
|
||||
* the specified <i>URI prefix</i>.
|
||||
*/
|
||||
NS_IMETHOD UnRegisterResourceFactory(const char* aURIPrefix) = 0;
|
||||
|
||||
|
||||
// Data source management routines
|
||||
|
||||
/**
|
||||
* Register a <i>named data source</i>. The RDF service will call
|
||||
* <tt>nsIRDFDataSource::GetURI()</tt> to determine the URI under which to
|
||||
* register the data source.
|
||||
*
|
||||
* Note that the data source will <i>not</i> be refcounted by the
|
||||
* RDF service! The assumption is that an RDF data source registers
|
||||
* with the service once it is initialized (via <tt>nsIRDFDataSource::Init()</tt>),
|
||||
* and unregisters when the last reference to the data source is
|
||||
* released.
|
||||
*/
|
||||
NS_IMETHOD RegisterDataSource(nsIRDFDataSource* dataSource) = 0;
|
||||
|
||||
/**
|
||||
* Unregister a <i>named data source</i>. The RDF service will call
|
||||
* <tt>nsIRDFDataSource::GetURI()</tt> to determine the URI under which the
|
||||
* data source was registered.
|
||||
*/
|
||||
NS_IMETHOD UnregisterDataSource(nsIRDFDataSource* dataSource) = 0;
|
||||
|
||||
/**
|
||||
* Register a constructor function that will create a named data source.
|
||||
* The RDF service will call this function to attempt to create a
|
||||
* named data source.
|
||||
*/
|
||||
NS_IMETHOD RegisterDataSourceConstructor(const char* aURI, NSDataSourceConstructorCallback aFn) = 0;
|
||||
|
||||
/**
|
||||
* Unregister the constructor function for a named data source.
|
||||
*/
|
||||
NS_IMETHOD UnregisterDataSourceConstructor(const char* aURI) = 0;
|
||||
|
||||
/**
|
||||
* Get the <i>named data source</i> corresponding to the URI. If a data
|
||||
* source has been registered via <tt>RegisterDataSource()</tt>, that
|
||||
* data source will be returned.
|
||||
*
|
||||
* If no data source is currently
|
||||
* registered for the specified URI, and a data source <i>constructor</i>
|
||||
* function has been registered via <tt>RegisterDatasourceConstructor()</tt>,
|
||||
* the RDF service will call the constructor to attempt to construct a
|
||||
* new data source. If construction is successful, the data source will
|
||||
* be initialized via <tt>nsIRDFDataSource::Init()</tt>.
|
||||
*/
|
||||
NS_IMETHOD GetDataSource(const char* uri, nsIRDFDataSource** dataSource) = 0;
|
||||
|
||||
/**
|
||||
* Create a database that contains the specified named data
|
||||
* sources. This is a convenience method whose functionality is
|
||||
* equivalent to (1) constructing a new nsIRDFDataBase object from
|
||||
* the repository, and (2) iteratively adding the named data sources
|
||||
* to it, in order.
|
||||
*/
|
||||
NS_IMETHOD CreateDatabase(const char** uris, nsIRDFDataBase** dataBase) = 0;
|
||||
|
||||
/**
|
||||
* Get the database aggregating all the stuff that Navigator sees as a default,
|
||||
* including a "local" store.
|
||||
*/
|
||||
NS_IMETHOD CreateBrowserDatabase(nsIRDFDataBase** dataBase) = 0;
|
||||
|
||||
};
|
||||
|
||||
// {BFD05261-834C-11d2-8EAC-00805F29F370}
|
||||
#define NS_IRDFSERVICE_IID \
|
||||
{ 0xbfd05261, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
extern nsresult
|
||||
NS_NewRDFService(nsIRDFService** result);
|
||||
|
||||
#endif // nsIRDFService_h__
|
||||
60
mozilla/rdf/base/public/nsIRDFTree.h
Normal file
60
mozilla/rdf/base/public/nsIRDFTree.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFTree_h__
|
||||
#define nsIRDFTree_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "prtypes.h"
|
||||
#include "rdf.h" // for error codes
|
||||
|
||||
/*
|
||||
An interface for presenting a tree view of an rdf datasource (or
|
||||
database).
|
||||
|
||||
Any datasource can also support nsIRDFTree. The interface is purely
|
||||
syntactic sugar for traversing simple tree where the child relation
|
||||
corresponds to the property type nc:child (nc = http://home.netscape.com/NC-rdf#).
|
||||
Each leaf is assumed to have a certain predefined set of properties
|
||||
such as creationDate, size, lastModificationDate, lastVisitDate, etc.
|
||||
|
||||
This interface is substantially less general than nsIRDFDataSource,
|
||||
but is adequate for bookmarks, the file system, history and a few
|
||||
other very commonly used data sources.
|
||||
|
||||
*/
|
||||
|
||||
// {7D7EEBD1-AA41-11d2-80B7-006097B76B8E}
|
||||
#define NS_IRDFTREE_IID \
|
||||
{ 0x7d7eebd1, 0xaa41, 0x11d2, { 0x80, 0xb7, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } };
|
||||
|
||||
class nsIRDFTree : public nsISupports {
|
||||
public:
|
||||
|
||||
NS_IMETHOD ListChildren (nsIRDFResource* folder, nsVoidArray** result);
|
||||
// XXX should define something called nsResourceArray and use that
|
||||
|
||||
NS_IMETHOD IsFolder (nsIRDFResource* node, PRBool* result);
|
||||
|
||||
NS_IMETHOD GetProperty (nsIRDFResource* node, nsIRDFResource* property,
|
||||
nsIRDFNode** result);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
185
mozilla/rdf/base/public/nsIRDFXMLDataSource.h
Normal file
185
mozilla/rdf/base/public/nsIRDFXMLDataSource.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This interface encapsulates information about an RDF/XML file,
|
||||
including the root resource, CSS style sheets, and named data
|
||||
sources.
|
||||
|
||||
This file also includes an observer interface for nsIRDFXMLDataSource
|
||||
objects.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFXMLDataSource_h__
|
||||
#define nsIRDFXMLDataSource_h__
|
||||
|
||||
#include "nsIRDFDataSource.h"
|
||||
class nsIOutputStream;
|
||||
class nsIURL;
|
||||
|
||||
// {EB1A5D30-AB33-11d2-8EC6-00805F29F370}
|
||||
#define NS_IRDFXMLDOCUMENTOBSERVER_IID \
|
||||
{ 0xeb1a5d30, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
class nsIRDFXMLDataSource;
|
||||
|
||||
class nsIRDFXMLDataSourceObserver : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Called when the RDF/XML document begins to load.
|
||||
*/
|
||||
NS_IMETHOD OnBeginLoad(nsIRDFXMLDataSource* aStream) = 0;
|
||||
|
||||
/**
|
||||
* Called when the RDF/XML document load is interrupted for some reason.
|
||||
*/
|
||||
NS_IMETHOD OnInterrupt(nsIRDFXMLDataSource* aStream) = 0;
|
||||
|
||||
/**
|
||||
* Called when an interrupted RDF/XML document load is resumed.
|
||||
*/
|
||||
NS_IMETHOD OnResume(nsIRDFXMLDataSource* aStream) = 0;
|
||||
|
||||
/**
|
||||
* Called whtn the RDF/XML document load is complete.
|
||||
*/
|
||||
NS_IMETHOD OnEndLoad(nsIRDFXMLDataSource* aStream) = 0;
|
||||
|
||||
/**
|
||||
* Called when the root resource of the RDF/XML document is found
|
||||
*/
|
||||
NS_IMETHOD OnRootResourceFound(nsIRDFXMLDataSource* aStream, nsIRDFResource* aResource) = 0;
|
||||
|
||||
/**
|
||||
* Called when a CSS style sheet is included (via XML processing
|
||||
* instruction) to the document.
|
||||
*/
|
||||
NS_IMETHOD OnCSSStyleSheetAdded(nsIRDFXMLDataSource* aStream, nsIURL* aCSSStyleSheetURL) = 0;
|
||||
|
||||
/**
|
||||
* Called when a named data source is included (via XML processing
|
||||
* instruction) to the document.
|
||||
*/
|
||||
NS_IMETHOD OnNamedDataSourceAdded(nsIRDFXMLDataSource* aStream, const char* aNamedDataSourceURI) = 0;
|
||||
};
|
||||
|
||||
|
||||
// {EB1A5D31-AB33-11d2-8EC6-00805F29F370}
|
||||
#define NS_IRDFXMLDATASOURCE_IID \
|
||||
{ 0xeb1a5d31, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
class nsIRDFXMLDataSource : public nsIRDFDataSource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Sets the RDF/XML stream to load either synchronously or
|
||||
* asynchronously when nsIRDFDataSource::Init() is called.
|
||||
* By default, the stream will load <em>asynchronously</em>.
|
||||
*/
|
||||
NS_IMETHOD SetSynchronous(PRBool aIsSynchronous) = 0;
|
||||
|
||||
/**
|
||||
* Sets the RDF/XML stream's read-only status. By default,
|
||||
* the stream will be read/write if the URL on which
|
||||
* nsIRDFDataSource::Init() is called is writable.
|
||||
*/
|
||||
NS_IMETHOD SetReadOnly(PRBool aIsReadOnly) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that the load is beginning.
|
||||
*/
|
||||
NS_IMETHOD BeginLoad(void) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that the load is being interrupted.
|
||||
*/
|
||||
NS_IMETHOD Interrupt(void) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that an interrupted load is being resumed.
|
||||
*/
|
||||
NS_IMETHOD Resume(void) = 0;
|
||||
|
||||
/**
|
||||
* Notify the document that the load is ending.
|
||||
*/
|
||||
NS_IMETHOD EndLoad(void) = 0;
|
||||
|
||||
/**
|
||||
* Set the root resource for the document.
|
||||
*/
|
||||
NS_IMETHOD SetRootResource(nsIRDFResource* aResource) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the root resource for the document.
|
||||
*/
|
||||
NS_IMETHOD GetRootResource(nsIRDFResource** aResource) = 0;
|
||||
|
||||
/**
|
||||
* Add a CSS style sheet to the document.
|
||||
* @param aStyleSheetURL An nsIURL object that is the URL of the style
|
||||
* sheet to add to the document.
|
||||
*/
|
||||
NS_IMETHOD AddCSSStyleSheetURL(nsIURL* aStyleSheetURL) = 0;
|
||||
|
||||
/**
|
||||
* Get the set of style sheets that have been included in the
|
||||
* document.
|
||||
* @param aStyleSheetURLs (out) A pointer to an array of pointers to nsIURL objects.
|
||||
* @param aCount (out) The number of nsIURL objects returned.
|
||||
*/
|
||||
NS_IMETHOD GetCSSStyleSheetURLs(nsIURL*** aStyleSheetURLs, PRInt32* aCount) = 0;
|
||||
|
||||
/**
|
||||
* Add a named data source to the document.
|
||||
* @param aNamedDataSoruceURI A URI identifying the data source.
|
||||
*/
|
||||
NS_IMETHOD AddNamedDataSourceURI(const char* aNamedDataSourceURI) = 0;
|
||||
|
||||
/**
|
||||
* Get the set of named data sources that have been included in
|
||||
* the document
|
||||
* @param aNamedDataSourceURIs (out) A pointer to an array of C-style character
|
||||
* strings.
|
||||
* @param aCount (out) The number of named data sources in the array.
|
||||
*/
|
||||
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount) = 0;
|
||||
|
||||
/**
|
||||
* Add an observer to the document. The observer will be notified of
|
||||
* RDF/XML events via the nsIRDFXMLDataSourceObserver interface. Note that
|
||||
* the observer is <em>not</em> reference counted.
|
||||
*/
|
||||
NS_IMETHOD AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver) = 0;
|
||||
|
||||
/**
|
||||
* Remove an observer from the document.
|
||||
*/
|
||||
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern nsresult
|
||||
NS_NewRDFXMLDataSource(nsIRDFXMLDataSource** result);
|
||||
|
||||
#endif // nsIRDFXMLDataSource_h__
|
||||
|
||||
@@ -16,22 +16,27 @@
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SparseSet.h"
|
||||
#include "BitSet.h"
|
||||
#include "Pool.h"
|
||||
/*
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
//
|
||||
void SparseSet::printPretty(LogModuleObject log)
|
||||
The RDF/XML source interface. An RDF/XML source is capable of
|
||||
producing serialized RDF/XML to an output stream.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFXMLSource_h__
|
||||
#define nsIRDFXMLSource_h__
|
||||
|
||||
class nsIOutputStream;
|
||||
|
||||
// {4DA56F10-99FE-11d2-8EBB-00805F29F370}
|
||||
#define NS_IRDFXMLSOURCE_IID \
|
||||
{ 0x4da56f10, 0x99fe, 0x11d2, { 0x8e, 0xbb, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
class nsIRDFXMLSource : public nsISupports
|
||||
{
|
||||
Pool pool;
|
||||
BitSet set(pool, universeSize);
|
||||
public:
|
||||
NS_IMETHOD Serialize(nsIOutputStream* aStream) = 0;
|
||||
};
|
||||
|
||||
for (Uint32 i = 0; i < count; i++)
|
||||
set.set(node[i].element);
|
||||
|
||||
set.printPretty(log);
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
#endif // nsIRDFXMLSource_h__
|
||||
64
mozilla/rdf/base/public/rdf.h
Normal file
64
mozilla/rdf/base/public/rdf.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A catch-all header file for miscellaneous RDF stuff. Currently
|
||||
contains error codes and vocabulary macros.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef rdf_h___
|
||||
#define rdf_h___
|
||||
|
||||
#include "nsError.h"
|
||||
|
||||
/*
|
||||
* The following macros are to aid in vocabulary definition.
|
||||
* They creates const char*'s for "kURI[prefix]_[name]" and
|
||||
* "kTag[prefix]_[name]", with appropriate complete namespace
|
||||
* qualification on the URI, e.g.,
|
||||
*
|
||||
* #define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
|
||||
* DEFINE_RDF_ELEMENT(RDF_NAMESPACE_URI, RDF, ID);
|
||||
*
|
||||
* will define:
|
||||
*
|
||||
* kURIRDF_ID to be "http://www.w3.org/TR/WD-rdf-syntax#ID", and
|
||||
* kTagRDF_ID to be "ID"
|
||||
*/
|
||||
|
||||
#define DEFINE_RDF_VOCAB(namespace, prefix, name) \
|
||||
static const char* kURI##prefix##_##name = ##namespace #name ;\
|
||||
static const char* kTag##prefix##_##name = kURI##prefix##_##name## + sizeof(##namespace) - 1
|
||||
|
||||
|
||||
/**
|
||||
* @name Standard RDF error codes
|
||||
*/
|
||||
|
||||
/*@{*/
|
||||
|
||||
/* Returned from nsIRDFCursor::Advance() if the cursor has no more
|
||||
elements to enuemrate */
|
||||
#define NS_ERROR_RDF_CURSOR_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_RDF, 1)
|
||||
#define NS_ERROR_RDF_NO_VALUE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_RDF, 2)
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif /* rdf_h___ */
|
||||
55
mozilla/rdf/base/src/Makefile.in
Normal file
55
mozilla/rdf/base/src/Makefile.in
Normal file
@@ -0,0 +1,55 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBRARY_NAME = rdfbase_s
|
||||
|
||||
CPPSRCS = \
|
||||
nsCompositeDataSource.cpp \
|
||||
nsContainerCursor.cpp \
|
||||
nsDefaultResourceFactory.cpp \
|
||||
nsEmptyCursor.cpp \
|
||||
nsInMemoryDataSource.cpp \
|
||||
nsRDFContentSink.cpp \
|
||||
nsRDFService.cpp \
|
||||
nsRDFXMLDataSource.cpp \
|
||||
rdfutil.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
MODULE = rdfbase
|
||||
|
||||
REQUIRES = netlib rdf raptor xpcom
|
||||
|
||||
MKSHLIB :=
|
||||
|
||||
# we don't want the shared lib
|
||||
NO_SHARED_LIB=1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
46
mozilla/rdf/base/src/makefile.win
Normal file
46
mozilla/rdf/base/src/makefile.win
Normal file
@@ -0,0 +1,46 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=rdf
|
||||
LIBRARY_NAME=rdfbase_s
|
||||
|
||||
CPP_OBJS=\
|
||||
.\$(OBJDIR)\nsCompositeDataSource.obj \
|
||||
.\$(OBJDIR)\nsContainerCursor.obj \
|
||||
.\$(OBJDIR)\nsDefaultResourceFactory.obj \
|
||||
.\$(OBJDIR)\nsEmptyCursor.obj \
|
||||
.\$(OBJDIR)\nsInMemoryDataSource.obj \
|
||||
.\$(OBJDIR)\nsRDFContentSink.obj \
|
||||
.\$(OBJDIR)\nsRDFService.obj \
|
||||
.\$(OBJDIR)\nsRDFXMLDataSource.obj \
|
||||
.\$(OBJDIR)\rdfutil.obj \
|
||||
$(NULL)
|
||||
|
||||
LINCS= -I$(PUBLIC)\rdf \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
-I$(PUBLIC)\raptor \
|
||||
-I$(PUBLIC)\netlib \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
libs:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
862
mozilla/rdf/base/src/nsCompositeDataSource.cpp
Normal file
862
mozilla/rdf/base/src/nsCompositeDataSource.cpp
Normal file
@@ -0,0 +1,862 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A simple composite data source implementation. A composit data
|
||||
source is just a strategy for combining individual data sources into
|
||||
a collective graph.
|
||||
|
||||
|
||||
1) A composite data source holds a sequence of data sources. The set
|
||||
of data sources can be specified during creation of the
|
||||
database. Data sources can also be added/deleted from a database
|
||||
later.
|
||||
|
||||
2) The aggregation mechanism is based on simple super-positioning of
|
||||
the graphs from the datasources. If there is a conflict (i.e.,
|
||||
data source A has a true arc from foo to bar while data source B
|
||||
has a false arc from foo to bar), the data source that it earlier
|
||||
in the sequence wins.
|
||||
|
||||
The implementation below doesn't really do this and needs to be
|
||||
fixed.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsRepository.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "prlog.h"
|
||||
|
||||
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFCompositeDataSourceIID, NS_IRDFCOMPOSITEDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFObserverIID, NS_IRDFOBSERVER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// CompositeDataSourceImpl
|
||||
|
||||
class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
protected:
|
||||
nsVoidArray* mObservers;
|
||||
|
||||
virtual ~CompositeDataSourceImpl(void);
|
||||
|
||||
public:
|
||||
CompositeDataSourceImpl(void);
|
||||
CompositeDataSourceImpl(char** dataSources);
|
||||
|
||||
nsVoidArray mDataSources;
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFDataSource interface
|
||||
NS_IMETHOD Init(const char* uri);
|
||||
|
||||
NS_IMETHOD GetURI(const char* *uri) const;
|
||||
|
||||
NS_IMETHOD GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source);
|
||||
|
||||
NS_IMETHOD GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** sources);
|
||||
|
||||
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target);
|
||||
|
||||
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** targets);
|
||||
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv);
|
||||
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target);
|
||||
|
||||
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion);
|
||||
|
||||
NS_IMETHOD AddObserver(nsIRDFObserver* n);
|
||||
|
||||
NS_IMETHOD RemoveObserver(nsIRDFObserver* n);
|
||||
|
||||
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels);
|
||||
|
||||
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels);
|
||||
|
||||
NS_IMETHOD Flush();
|
||||
|
||||
NS_IMETHOD IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult);
|
||||
|
||||
NS_IMETHOD DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget);
|
||||
|
||||
|
||||
// nsIRDFCompositeDataSource interface
|
||||
NS_IMETHOD AddDataSource(nsIRDFDataSource* source);
|
||||
NS_IMETHOD RemoveDataSource(nsIRDFDataSource* source);
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object);
|
||||
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object);
|
||||
|
||||
// Implementation methods
|
||||
PRBool HasAssertionN(int n, nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DBArcsInOutCursor : public nsIRDFArcsOutCursor,
|
||||
public nsIRDFArcsInCursor
|
||||
{
|
||||
CompositeDataSourceImpl* mCompositeDataSourceImpl;
|
||||
nsIRDFResource* mSource;
|
||||
nsIRDFNode* mTarget;
|
||||
PRInt32 mCount;
|
||||
nsIRDFArcsOutCursor* mOutCursor;
|
||||
nsIRDFArcsInCursor* mInCursor;
|
||||
nsVoidArray mResults;
|
||||
|
||||
public:
|
||||
DBArcsInOutCursor(CompositeDataSourceImpl* db, nsIRDFNode* node, PRBool arcsOutp);
|
||||
|
||||
virtual ~DBArcsInOutCursor();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
|
||||
return (mInCursor ? mInCursor->GetDataSource(aDataSource) :
|
||||
mOutCursor->GetDataSource(aDataSource));
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
|
||||
return mOutCursor->GetSubject(aResource);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aNode) {
|
||||
return mInCursor->GetObject(aNode);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
|
||||
return (mInCursor ? mInCursor->GetPredicate(aPredicate) :
|
||||
mOutCursor->GetPredicate(aPredicate));
|
||||
}
|
||||
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
|
||||
return (mInCursor ? mInCursor->GetValue(aValue) :
|
||||
mOutCursor->GetValue(aValue));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
DBArcsInOutCursor::DBArcsInOutCursor(CompositeDataSourceImpl* db,
|
||||
nsIRDFNode* node,
|
||||
PRBool arcsOutp)
|
||||
: mCompositeDataSourceImpl(db),
|
||||
mTarget(0),
|
||||
mSource(0),
|
||||
mCount(0),
|
||||
mInCursor(0),
|
||||
mOutCursor(0)
|
||||
{
|
||||
if (arcsOutp) {
|
||||
mSource = (nsIRDFResource*) node;
|
||||
} else {
|
||||
mTarget = node;
|
||||
}
|
||||
NS_IF_ADDREF(node);
|
||||
|
||||
// XXX there better be at least _one_ datasource in this here
|
||||
// CompositeDataSourceImpl, else this'll be a real short ride...
|
||||
PR_ASSERT(db->mDataSources.Count() > 0);
|
||||
nsIRDFDataSource* ds = (nsIRDFDataSource*) db->mDataSources[mCount++];
|
||||
|
||||
if (mTarget) {
|
||||
ds->ArcLabelsIn(mTarget, &mInCursor);
|
||||
} else {
|
||||
ds->ArcLabelsOut(mSource, &mOutCursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DBArcsInOutCursor::~DBArcsInOutCursor(void)
|
||||
{
|
||||
for (PRInt32 i = mResults.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFNode* node = (nsIRDFNode*) mResults[i];
|
||||
NS_RELEASE(node);
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mSource);
|
||||
NS_IF_RELEASE(mTarget);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(DBArcsInOutCursor);
|
||||
NS_IMPL_RELEASE(DBArcsInOutCursor);
|
||||
|
||||
NS_IMETHODIMP_(nsresult)
|
||||
DBArcsInOutCursor::QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFArcsOutCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFArcsOutCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DBArcsInOutCursor::Advance(void)
|
||||
{
|
||||
nsIRDFDataSource* ds;
|
||||
while (mInCursor || mOutCursor) {
|
||||
nsresult result = (mInCursor ? mInCursor->Advance() : mOutCursor->Advance());
|
||||
|
||||
while (NS_SUCCEEDED(result)) {
|
||||
nsIRDFNode* obj ;
|
||||
GetValue(&obj);
|
||||
if (mResults.IndexOf(obj) < 0) {
|
||||
mResults.AppendElement(obj);
|
||||
return NS_OK;
|
||||
}
|
||||
result = (mInCursor ? mInCursor->Advance() : mOutCursor->Advance());
|
||||
}
|
||||
|
||||
if (result != NS_ERROR_RDF_CURSOR_EMPTY)
|
||||
return result;
|
||||
|
||||
NS_IF_RELEASE(mInCursor);
|
||||
NS_IF_RELEASE(mOutCursor);
|
||||
|
||||
if (mCount >= mCompositeDataSourceImpl->mDataSources.Count())
|
||||
break;
|
||||
|
||||
ds = (nsIRDFDataSource*) mCompositeDataSourceImpl->mDataSources[mCount];
|
||||
++mCount;
|
||||
|
||||
if (mTarget) {
|
||||
ds->ArcLabelsIn(mTarget, &mInCursor);
|
||||
} else {
|
||||
ds->ArcLabelsOut(mSource, &mOutCursor);
|
||||
}
|
||||
}
|
||||
return NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// DBAssertionCursor
|
||||
//
|
||||
// An assertion cursor implementation for the db.
|
||||
//
|
||||
class DBGetSTCursor : public nsIRDFAssertionCursor
|
||||
{
|
||||
private:
|
||||
CompositeDataSourceImpl* mCompositeDataSourceImpl;
|
||||
nsIRDFResource* mSource;
|
||||
nsIRDFResource* mLabel;
|
||||
nsIRDFNode* mTarget;
|
||||
PRInt32 mCount;
|
||||
PRBool mTruthValue;
|
||||
nsIRDFAssertionCursor* mCurrentCursor;
|
||||
|
||||
public:
|
||||
DBGetSTCursor(CompositeDataSourceImpl* db, nsIRDFNode* u,
|
||||
nsIRDFResource* property, PRBool inversep, PRBool tv);
|
||||
|
||||
virtual ~DBGetSTCursor();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFAssertionCursor interface
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
|
||||
return mCurrentCursor->GetDataSource(aDataSource);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
|
||||
return mCurrentCursor->GetSubject(aResource);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
|
||||
return mCurrentCursor->GetPredicate(aPredicate);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aObject) {
|
||||
return mCurrentCursor->GetObject(aObject);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
|
||||
return mCurrentCursor->GetTruthValue(aTruthValue);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
|
||||
return mCurrentCursor->GetValue(aValue);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//NS_IMPL_ISUPPORTS(DBGetSTCursor, kIRDFAssertionCursorIID);
|
||||
|
||||
DBGetSTCursor::DBGetSTCursor(CompositeDataSourceImpl* db,
|
||||
nsIRDFNode* u,
|
||||
nsIRDFResource* property,
|
||||
PRBool inversep,
|
||||
PRBool tv)
|
||||
: mCompositeDataSourceImpl(db),
|
||||
mSource(nsnull),
|
||||
mLabel(property),
|
||||
mTarget(nsnull),
|
||||
mCount(0),
|
||||
mTruthValue(tv)
|
||||
{
|
||||
if (!inversep) {
|
||||
mSource = (nsIRDFResource*) u;
|
||||
} else {
|
||||
mTarget = u;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(mSource);
|
||||
NS_IF_ADDREF(mTarget);
|
||||
NS_IF_ADDREF(mLabel);
|
||||
|
||||
// XXX assume that at least one data source exists in the CompositeDataSourceImpl.
|
||||
nsIRDFDataSource* ds = (nsIRDFDataSource*) db->mDataSources[mCount++];
|
||||
if (mSource)
|
||||
ds->GetTargets(mSource, mLabel, mTruthValue, &mCurrentCursor);
|
||||
else
|
||||
ds->GetSources(mLabel, mTarget, mTruthValue, &mCurrentCursor);
|
||||
}
|
||||
|
||||
|
||||
DBGetSTCursor::~DBGetSTCursor(void)
|
||||
{
|
||||
NS_IF_RELEASE(mLabel);
|
||||
NS_IF_RELEASE(mSource);
|
||||
NS_IF_ADDREF(mTarget);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(DBGetSTCursor);
|
||||
NS_IMPL_RELEASE(DBGetSTCursor);
|
||||
|
||||
NS_IMETHODIMP_(nsresult)
|
||||
DBGetSTCursor::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFAssertionCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DBGetSTCursor::Advance(void)
|
||||
{
|
||||
nsIRDFDataSource* ds;
|
||||
while (mCurrentCursor) {
|
||||
nsresult result = mCurrentCursor->Advance();
|
||||
while (NS_ERROR_RDF_CURSOR_EMPTY != result) {
|
||||
nsIRDFResource* src;
|
||||
nsIRDFNode* trg;
|
||||
mCurrentCursor->GetSubject(&src);
|
||||
mCurrentCursor->GetObject(&trg);
|
||||
if (!mCompositeDataSourceImpl->HasAssertionN(mCount-1, src, mLabel, trg, !mTruthValue)) {
|
||||
return NS_OK;
|
||||
} else {
|
||||
result = mCurrentCursor->Advance();
|
||||
}
|
||||
}
|
||||
|
||||
if (mCount >= mCompositeDataSourceImpl->mDataSources.Count())
|
||||
break;
|
||||
|
||||
ds = (nsIRDFDataSource*) mCompositeDataSourceImpl->mDataSources[mCount];
|
||||
++mCount;
|
||||
|
||||
if (mSource)
|
||||
ds->GetTargets(mSource, mLabel, mTruthValue, &mCurrentCursor);
|
||||
else
|
||||
ds->GetSources(mLabel, mTarget, mTruthValue, &mCurrentCursor);
|
||||
}
|
||||
return NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result)
|
||||
{
|
||||
CompositeDataSourceImpl* db = new CompositeDataSourceImpl();
|
||||
if (! db)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*result = db;
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
CompositeDataSourceImpl::CompositeDataSourceImpl(void)
|
||||
: mObservers(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
CompositeDataSourceImpl::~CompositeDataSourceImpl(void)
|
||||
{
|
||||
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
ds->RemoveObserver(this);
|
||||
NS_IF_RELEASE(ds);
|
||||
}
|
||||
delete mObservers;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports interface
|
||||
|
||||
NS_IMPL_ADDREF(CompositeDataSourceImpl);
|
||||
NS_IMPL_RELEASE(CompositeDataSourceImpl);
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFCompositeDataSourceIID) ||
|
||||
iid.Equals(kIRDFDataSourceIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFCompositeDataSource*, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
else if (iid.Equals(kIRDFObserverIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFObserver*, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
*result = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFDataSource interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::Init(const char* uri)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_UNEXPECTED; // XXX CompositeDataSourceImpl doesn't have a URI?
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::GetURI(const char* *uri) const
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_UNEXPECTED; // XXX CompositeDataSourceImpl doesn't have a URI?
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source)
|
||||
{
|
||||
PRInt32 count = mDataSources.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
|
||||
if (NS_FAILED(ds->GetSource(property, target, tv, source)))
|
||||
continue;
|
||||
|
||||
// okay, found it. make sure we don't have the opposite
|
||||
// asserted in a more local data source
|
||||
if (!HasAssertionN(count-1, *source, property, target, !tv))
|
||||
return NS_OK;
|
||||
|
||||
NS_RELEASE(*source);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = new DBGetSTCursor(this, target, property, 1, tv);
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target)
|
||||
{
|
||||
PRInt32 count = mDataSources.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
|
||||
if (NS_FAILED(ds->GetTarget(source, property, tv, target)))
|
||||
continue;
|
||||
|
||||
// okay, found it. make sure we don't have the opposite
|
||||
// asserted in the "local" data source
|
||||
if (!HasAssertionN(count-1, source, property, *target, !tv))
|
||||
return NS_OK;
|
||||
|
||||
|
||||
NS_RELEASE(*target);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
CompositeDataSourceImpl::HasAssertionN(int n,
|
||||
nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv)
|
||||
{
|
||||
int m = 0;
|
||||
PRBool result = 0;
|
||||
while (m < n) {
|
||||
nsIRDFDataSource* ds = (nsIRDFDataSource*) mDataSources[m];
|
||||
ds->HasAssertion(source, property, target, tv, &result);
|
||||
if (result) return 1;
|
||||
m++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** targets)
|
||||
{
|
||||
if (! targets)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIRDFAssertionCursor* result;
|
||||
result = new DBGetSTCursor(this, source, property, 0, tv);
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(result);
|
||||
*targets = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv)
|
||||
{
|
||||
// Need to add back the stuff for unblocking ...
|
||||
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
if (NS_SUCCEEDED(ds->Assert(source, property, target, tv)))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 count = mDataSources.Count();
|
||||
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
if (NS_FAILED(rv = ds->Unassert(source, property, target)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
nsIRDFDataSource* ds0 = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[0]);
|
||||
rv = ds0->Assert(source, property, target, PR_FALSE);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
||||
// Otherwise, look through all the data sources to see if anyone
|
||||
// has the positive...
|
||||
PRInt32 count = mDataSources.Count();
|
||||
PRBool hasNegation = 0;
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
if (NS_FAILED(rv = ds->HasAssertion(source, property, target, tv, hasAssertion)))
|
||||
return rv;
|
||||
|
||||
if (*hasAssertion)
|
||||
return NS_OK;
|
||||
|
||||
if (NS_FAILED(rv = ds->HasAssertion(source, property, target, !tv, &hasNegation)))
|
||||
return rv;
|
||||
|
||||
if (hasNegation) {
|
||||
*hasAssertion = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, nobody had the assertion at all
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::AddObserver(nsIRDFObserver* obs)
|
||||
{
|
||||
if (!mObservers) {
|
||||
if ((mObservers = new nsVoidArray()) == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// XXX ensure uniqueness
|
||||
|
||||
mObservers->AppendElement(obs);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::RemoveObserver(nsIRDFObserver* obs)
|
||||
{
|
||||
if (!mObservers)
|
||||
return NS_OK;
|
||||
|
||||
mObservers->RemoveElement(obs);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels)
|
||||
{
|
||||
if (! labels)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIRDFArcsInCursor* result = new DBArcsInOutCursor(this, node, 0);
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_ADDREF(result);
|
||||
*labels = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels)
|
||||
{
|
||||
if (! labels)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIRDFArcsOutCursor* result = new DBArcsInOutCursor(this, source, 1);
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_ADDREF(result);
|
||||
*labels = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::Flush()
|
||||
{
|
||||
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
|
||||
ds->Flush();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFCompositeDataSource methods
|
||||
// XXX rvg We should make this take an additional argument specifying where
|
||||
// in the sequence of data sources (of the db), the new data source should
|
||||
// fit in. Right now, the new datasource gets stuck at the end.
|
||||
// need to add the observers of the CompositeDataSourceImpl to the new data source.
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* source)
|
||||
{
|
||||
if (! source)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mDataSources.InsertElementAt(source, 0);
|
||||
source->AddObserver(this);
|
||||
NS_ADDREF(source);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* source)
|
||||
{
|
||||
if (! source)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
||||
if (mDataSources.IndexOf(source) >= 0) {
|
||||
mDataSources.RemoveElement(source);
|
||||
source->RemoveObserver(this);
|
||||
NS_RELEASE(source);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::OnAssert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
if (mObservers) {
|
||||
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnAssert(subject, predicate, object);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::OnUnassert(nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
if (mObservers) {
|
||||
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnUnassert(subject, predicate, object);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
316
mozilla/rdf/base/src/nsContainerCursor.cpp
Normal file
316
mozilla/rdf/base/src/nsContainerCursor.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A simple cursor that enumerates the elements of an RDF container
|
||||
(RDF:Bag, RDF:Seq, or RDF:Alt).
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
1. This uses an implementation-specific detail to determine the
|
||||
index of the last element in the container; specifically, the RDF
|
||||
utilities maintain a counter attribute on the container that
|
||||
holds the numeric value of the next value that is to be
|
||||
assigned. So, this cursor will bust if you use it with a bag that
|
||||
hasn't been created using the RDF utility routines.
|
||||
|
||||
2. This is sort of a continuation of (1), but -- it's not smart
|
||||
enough to notice duplicates.
|
||||
|
||||
TODO. This is way too brain dead to handle aggregated RDF
|
||||
databases. It needs to be upgraded in a big way.
|
||||
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "prlog.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
|
||||
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ContainerCursorImpl : public nsIRDFAssertionCursor {
|
||||
private:
|
||||
nsIRDFService* mRDFService;
|
||||
nsIRDFDataSource* mDataSource;
|
||||
nsIRDFResource* mContainer;
|
||||
nsIRDFNode* mNext;
|
||||
PRInt32 mCounter;
|
||||
|
||||
public:
|
||||
ContainerCursorImpl(nsIRDFDataSource* ds, nsIRDFResource* container);
|
||||
virtual ~ContainerCursorImpl(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Advance(void);
|
||||
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aResource);
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate);
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aObject);
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue);
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue);
|
||||
};
|
||||
|
||||
ContainerCursorImpl::ContainerCursorImpl(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container)
|
||||
: mDataSource(ds), mContainer(container), mNext(nsnull), mCounter(1)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_IF_ADDREF(mDataSource);
|
||||
NS_IF_ADDREF(mContainer);
|
||||
|
||||
nsresult rv;
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &mRDFService);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to acquire resource manager");
|
||||
|
||||
NS_ASSERTION(rdf_IsContainer(mDataSource, container), "not a container");
|
||||
}
|
||||
|
||||
|
||||
ContainerCursorImpl::~ContainerCursorImpl(void)
|
||||
{
|
||||
NS_IF_RELEASE(mNext);
|
||||
|
||||
if (mRDFService)
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService);
|
||||
|
||||
NS_IF_RELEASE(mContainer);
|
||||
NS_IF_RELEASE(mDataSource);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(ContainerCursorImpl);
|
||||
NS_IMPL_RELEASE(ContainerCursorImpl);
|
||||
|
||||
NS_IMETHODIMP_(nsresult)
|
||||
ContainerCursorImpl::QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFAssertionCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::Advance(void)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// release the last value that we were holding
|
||||
NS_IF_RELEASE(mNext);
|
||||
|
||||
nsIRDFResource* RDF_nextVal = nsnull;
|
||||
nsIRDFNode* nextNode = nsnull;
|
||||
nsIRDFLiteral* nextVal = nsnull;
|
||||
const PRUnichar* p;
|
||||
nsAutoString s;
|
||||
PRInt32 last;
|
||||
PRInt32 err;
|
||||
|
||||
// XXX we could cache all this crap when the cursor gets created.
|
||||
if (NS_FAILED(rv = mRDFService->GetResource(kURIRDF_nextVal, &RDF_nextVal)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = mDataSource->GetTarget(mContainer, RDF_nextVal, PR_TRUE, &nextNode)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nextNode->QueryInterface(kIRDFLiteralIID, (void**) &nextVal)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nextVal->GetValue(&p)))
|
||||
goto done;
|
||||
|
||||
s = p;
|
||||
last = s.ToInteger(&err);
|
||||
if (NS_FAILED(err))
|
||||
goto done;
|
||||
|
||||
// initialize rv to the case where mCounter has advanced past the
|
||||
// last element
|
||||
rv = NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
|
||||
while (mCounter < last) {
|
||||
nsIRDFResource* ordinalProperty = nsnull;
|
||||
if (NS_FAILED(rv = GetPredicate(&ordinalProperty)))
|
||||
break;
|
||||
|
||||
rv = mDataSource->GetTarget(mContainer, ordinalProperty, PR_TRUE, &mNext);
|
||||
NS_IF_RELEASE(ordinalProperty);
|
||||
|
||||
++mCounter;
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Don't bother releasing mNext; we'll let the AddRef
|
||||
// serve as the implicit addref that GetNext() should
|
||||
// perform.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(nextNode);
|
||||
NS_IF_RELEASE(nextVal);
|
||||
NS_IF_RELEASE(RDF_nextVal);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetDataSource(nsIRDFDataSource** aDataSource)
|
||||
{
|
||||
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_ADDREF(mDataSource);
|
||||
*aDataSource = mDataSource;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetSubject(nsIRDFResource** aSubject)
|
||||
{
|
||||
NS_PRECONDITION(aSubject != nsnull, "null ptr");
|
||||
if (! aSubject)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_ADDREF(mContainer);
|
||||
*aSubject = mContainer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetPredicate(nsIRDFResource** aPredicate)
|
||||
{
|
||||
NS_PRECONDITION(aPredicate != nsnull, "null ptr");
|
||||
|
||||
nsAutoString s(kRDFNameSpaceURI);
|
||||
s.Append("_");
|
||||
s.Append(mCounter, 10);
|
||||
|
||||
// this'll AddRef(), null check, etc.
|
||||
return mRDFService->GetUnicodeResource(s, aPredicate);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetObject(nsIRDFNode** aObject)
|
||||
{
|
||||
NS_PRECONDITION(aObject != nsnull, "null ptr");
|
||||
if (! aObject)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mNext)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
NS_ADDREF(mNext);
|
||||
*aObject = mNext;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetValue(nsIRDFNode** aObject)
|
||||
{
|
||||
NS_PRECONDITION(aObject != nsnull, "null ptr");
|
||||
if (! aObject)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mNext)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
NS_ADDREF(mNext);
|
||||
*aObject = mNext;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContainerCursorImpl::GetTruthValue(PRBool* aTruthValue)
|
||||
{
|
||||
NS_PRECONDITION(aTruthValue != nsnull, "null ptr");
|
||||
if (! aTruthValue)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aTruthValue = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewContainerCursor(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container,
|
||||
nsIRDFAssertionCursor** cursor)
|
||||
{
|
||||
NS_PRECONDITION(ds != nsnull, "null ptr");
|
||||
NS_PRECONDITION(container != nsnull, "null ptr");
|
||||
NS_PRECONDITION(cursor != nsnull, "null ptr");
|
||||
|
||||
if (!ds || !container || !cursor)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
ContainerCursorImpl* result = new ContainerCursorImpl(ds, container);
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*cursor = result;
|
||||
NS_ADDREF(result);
|
||||
return NS_OK;
|
||||
}
|
||||
229
mozilla/rdf/base/src/nsDefaultResourceFactory.cpp
Normal file
229
mozilla/rdf/base/src/nsDefaultResourceFactory.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The default resource factory implementation. This resource factory
|
||||
produces nsIRDFResource objects for any URI prefix that is not
|
||||
covered by some other factory.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFResourceFactory.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "plstr.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceFactoryIID, NS_IRDFRESOURCEFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DefaultResourceImpl : public nsIRDFResource
|
||||
{
|
||||
public:
|
||||
DefaultResourceImpl(const char* uri);
|
||||
virtual ~DefaultResourceImpl(void);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFNode
|
||||
NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const;
|
||||
|
||||
// nsIRDFResource
|
||||
NS_IMETHOD GetValue(const char* *uri) const;
|
||||
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const;
|
||||
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const;
|
||||
|
||||
// Implementation methods
|
||||
const char* GetURI(void) const {
|
||||
return mURI;
|
||||
}
|
||||
|
||||
private:
|
||||
char* mURI;
|
||||
};
|
||||
|
||||
|
||||
DefaultResourceImpl::DefaultResourceImpl(const char* uri)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mURI = PL_strdup(uri);
|
||||
}
|
||||
|
||||
|
||||
DefaultResourceImpl::~DefaultResourceImpl(void)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsIRDFService* mgr;
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &mgr);
|
||||
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mgr->UnCacheResource(this);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, mgr);
|
||||
}
|
||||
|
||||
// N.B. that we need to free the URI *after* we un-cache the resource,
|
||||
// due to the way that the resource manager is implemented.
|
||||
PL_strfree(mURI);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(DefaultResourceImpl);
|
||||
NS_IMPL_RELEASE(DefaultResourceImpl);
|
||||
|
||||
nsresult
|
||||
DefaultResourceImpl::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = nsnull;
|
||||
if (iid.Equals(kIRDFResourceIID) ||
|
||||
iid.Equals(kIRDFNodeIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFResource*, this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DefaultResourceImpl::EqualsNode(nsIRDFNode* node, PRBool* result) const
|
||||
{
|
||||
nsresult rv;
|
||||
nsIRDFResource* resource;
|
||||
if (NS_SUCCEEDED(node->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
|
||||
rv = EqualsResource(resource, result);
|
||||
NS_RELEASE(resource);
|
||||
}
|
||||
else {
|
||||
*result = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DefaultResourceImpl::GetValue(const char* *uri) const
|
||||
{
|
||||
if (!uri)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*uri = mURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DefaultResourceImpl::EqualsResource(const nsIRDFResource* resource, PRBool* result) const
|
||||
{
|
||||
if (!resource || !result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = (resource == this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DefaultResourceImpl::EqualsString(const char* uri, PRBool* result) const
|
||||
{
|
||||
if (!uri || !result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = (PL_strcmp(uri, mURI) == 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DefaultResourceFactoryImpl : public nsIRDFResourceFactory
|
||||
{
|
||||
public:
|
||||
DefaultResourceFactoryImpl(void);
|
||||
virtual ~DefaultResourceFactoryImpl(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult);
|
||||
};
|
||||
|
||||
|
||||
DefaultResourceFactoryImpl::DefaultResourceFactoryImpl(void)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
DefaultResourceFactoryImpl::~DefaultResourceFactoryImpl(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(DefaultResourceFactoryImpl, kIRDFResourceFactoryIID);
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DefaultResourceFactoryImpl::CreateResource(const char* aURI, nsIRDFResource** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DefaultResourceImpl* resource = new DefaultResourceImpl(aURI);
|
||||
if (! resource)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(resource);
|
||||
*aResult = resource;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFDefaultResourceFactory(nsIRDFResourceFactory** result)
|
||||
{
|
||||
NS_PRECONDITION(result != nsnull, "null ptr");
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DefaultResourceFactoryImpl* factory = new DefaultResourceFactoryImpl();
|
||||
if (! factory)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(factory);
|
||||
*result = factory;
|
||||
return NS_OK;
|
||||
}
|
||||
240
mozilla/rdf/base/src/nsEmptyCursor.cpp
Normal file
240
mozilla/rdf/base/src/nsEmptyCursor.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A set of "empty cursors" (nsIRDFAssertionCursor,
|
||||
nsIRDFArcsOutCursor, nsIRDFArcsInCursor) that can be used to ensure
|
||||
that the data source methods which return a cursor always return
|
||||
*something*.
|
||||
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
|
||||
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EmptyAssertionCursorImpl : public nsIRDFAssertionCursor
|
||||
{
|
||||
public:
|
||||
EmptyAssertionCursorImpl(void) {};
|
||||
virtual ~EmptyAssertionCursorImpl(void) {};
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFAssertionCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
// nsIRDFCursor
|
||||
NS_IMETHOD Advance(void) {
|
||||
return NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
}
|
||||
|
||||
// nsIRDFAssertionCursor
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aObject) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewEmptyRDFAssertionCursor(nsIRDFAssertionCursor** result)
|
||||
{
|
||||
static EmptyAssertionCursorImpl gEmptyAssertionCursor;
|
||||
*result = &gEmptyAssertionCursor;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EmptyArcsOutCursorImpl : public nsIRDFArcsOutCursor
|
||||
{
|
||||
public:
|
||||
EmptyArcsOutCursorImpl(void) {};
|
||||
virtual ~EmptyArcsOutCursorImpl(void) {};
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFArcsOutCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFArcsOutCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
// nsIRDFCursor
|
||||
NS_IMETHOD Advance(void) {
|
||||
return NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
}
|
||||
|
||||
// nsIRDFArcsOutCursor
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewEmptyRDFArcsOutCursor(nsIRDFArcsOutCursor** result)
|
||||
{
|
||||
static EmptyArcsOutCursorImpl gEmptyArcsOutCursor;
|
||||
*result = &gEmptyArcsOutCursor;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EmptyArcsInCursorImpl : public nsIRDFArcsInCursor
|
||||
{
|
||||
public:
|
||||
EmptyArcsInCursorImpl(void) {};
|
||||
virtual ~EmptyArcsInCursorImpl(void) {};
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kIRDFArcsInCursorIID) ||
|
||||
iid.Equals(kIRDFCursorIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFArcsInCursor*, this);
|
||||
/* AddRef(); // not necessary */
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
// nsIRDFCursor
|
||||
NS_IMETHOD Advance(void) {
|
||||
return NS_ERROR_RDF_CURSOR_EMPTY;
|
||||
}
|
||||
|
||||
// nsIRDFArcsInCursor
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetObject(nsIRDFNode** aNode) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewEmptyRDFArcsInCursor(nsIRDFArcsInCursor** result)
|
||||
{
|
||||
static EmptyArcsInCursorImpl gEmptyArcsInCursor;
|
||||
*result = &gEmptyArcsInCursor;
|
||||
return NS_OK;
|
||||
}
|
||||
1404
mozilla/rdf/base/src/nsInMemoryDataSource.cpp
Normal file
1404
mozilla/rdf/base/src/nsInMemoryDataSource.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,23 +16,25 @@
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ASSIGNER_H_
|
||||
#define _REGISTER_ASSIGNER_H_
|
||||
/*
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
This header file just contains prototypes for the factory methods
|
||||
for "builtin" data sources that are included in rdf.dll.
|
||||
|
||||
class FastBitMatrix;
|
||||
Each of these data sources is exposed to the external world via its
|
||||
CID in ../include/nsRDFCID.h.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsBaseDataSources_h__
|
||||
#define nsBaseDataSources_h__
|
||||
|
||||
#include "nsError.h"
|
||||
class nsIRDFDataSource;
|
||||
|
||||
// in nsInMemoryDataSource.cpp
|
||||
nsresult NS_NewRDFInMemoryDataSource(nsIRDFDataSource** result);
|
||||
|
||||
#endif // nsBaseDataSources_h__
|
||||
|
||||
class RegisterAssigner
|
||||
{
|
||||
protected:
|
||||
VirtualRegisterManager& vRegManager;
|
||||
|
||||
public:
|
||||
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
|
||||
|
||||
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
|
||||
};
|
||||
|
||||
#endif /* _REGISTER_ASSIGNER_H_ */
|
||||
1512
mozilla/rdf/base/src/nsRDFContentSink.cpp
Normal file
1512
mozilla/rdf/base/src/nsRDFContentSink.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
mozilla/rdf/base/src/nsRDFContentSink.h
Normal file
137
mozilla/rdf/base/src/nsRDFContentSink.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsRDFContentSink_h__
|
||||
#define nsRDFContentSink_h__
|
||||
|
||||
#include "nsIRDFContentSink.h"
|
||||
|
||||
class nsIURL;
|
||||
class nsVoidArray;
|
||||
class nsIRDFResource;
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFService;
|
||||
class nsINameSpaceManager;
|
||||
|
||||
typedef enum {
|
||||
eRDFContentSinkState_InProlog,
|
||||
eRDFContentSinkState_InDocumentElement,
|
||||
eRDFContentSinkState_InDescriptionElement,
|
||||
eRDFContentSinkState_InContainerElement,
|
||||
eRDFContentSinkState_InPropertyElement,
|
||||
eRDFContentSinkState_InMemberElement,
|
||||
eRDFContentSinkState_InEpilog
|
||||
} RDFContentSinkState;
|
||||
|
||||
|
||||
class RDFContentSinkImpl : public nsIRDFContentSink
|
||||
{
|
||||
public:
|
||||
RDFContentSinkImpl();
|
||||
virtual ~RDFContentSinkImpl();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentSink
|
||||
NS_IMETHOD WillBuildModel(void);
|
||||
NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel);
|
||||
NS_IMETHOD WillInterrupt(void);
|
||||
NS_IMETHOD WillResume(void);
|
||||
NS_IMETHOD SetParser(nsIParser* aParser);
|
||||
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddComment(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
|
||||
NS_IMETHOD NotifyError(nsresult aErrorResult);
|
||||
|
||||
// nsIXMLContentSink
|
||||
NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddCharacterData(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddUnparsedEntity(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddNotation(const nsIParserNode& aNode);
|
||||
NS_IMETHOD AddEntityReference(const nsIParserNode& aNode);
|
||||
|
||||
// nsIRDFContentSink
|
||||
NS_IMETHOD SetDataSource(nsIRDFDataSource* ds);
|
||||
NS_IMETHOD GetDataSource(nsIRDFDataSource*& ds);
|
||||
NS_IMETHOD Init(nsIURL* aURL, nsINameSpaceManager* aNameSpaceManager);
|
||||
|
||||
protected:
|
||||
// Text management
|
||||
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
|
||||
PRBool* aDidFlush=nsnull);
|
||||
|
||||
PRUnichar* mText;
|
||||
PRInt32 mTextLength;
|
||||
PRInt32 mTextSize;
|
||||
PRBool mConstrainSize;
|
||||
|
||||
// namespace management
|
||||
void PushNameSpacesFrom(const nsIParserNode& aNode);
|
||||
nsIAtom* CutNameSpacePrefix(nsString& aString);
|
||||
PRInt32 GetNameSpaceID(nsIAtom* aPrefix);
|
||||
void GetNameSpaceURI(PRInt32 aID, nsString& aURI);
|
||||
void PopNameSpaces();
|
||||
|
||||
nsINameSpaceManager* mNameSpaceManager;
|
||||
nsVoidArray* mNameSpaceStack;
|
||||
PRInt32 mRDFNameSpaceID;
|
||||
|
||||
void SplitQualifiedName(const nsString& aQualifiedName,
|
||||
PRInt32& rNameSpaceID,
|
||||
nsString& rProperty);
|
||||
|
||||
// RDF-specific parsing
|
||||
nsresult GetIdAboutAttribute(const nsIParserNode& aNode, nsString& rResource);
|
||||
nsresult GetResourceAttribute(const nsIParserNode& aNode, nsString& rResource);
|
||||
nsresult AddProperties(const nsIParserNode& aNode, nsIRDFResource* aSubject);
|
||||
|
||||
virtual nsresult OpenRDF(const nsIParserNode& aNode);
|
||||
virtual nsresult OpenObject(const nsIParserNode& aNode);
|
||||
virtual nsresult OpenProperty(const nsIParserNode& aNode);
|
||||
virtual nsresult OpenMember(const nsIParserNode& aNode);
|
||||
virtual nsresult OpenValue(const nsIParserNode& aNode);
|
||||
|
||||
// Miscellaneous RDF junk
|
||||
nsIRDFService* mRDFService;
|
||||
nsIRDFDataSource* mDataSource;
|
||||
RDFContentSinkState mState;
|
||||
|
||||
// content stack management
|
||||
PRInt32 PushContext(nsIRDFResource *aContext, RDFContentSinkState aState);
|
||||
nsresult PopContext(nsIRDFResource*& rContext, RDFContentSinkState& rState);
|
||||
nsIRDFResource* GetContextElement(PRInt32 ancestor = 0);
|
||||
|
||||
nsVoidArray* mContextStack;
|
||||
|
||||
nsIURL* mDocumentURL;
|
||||
PRUint32 mGenSym; // for generating anonymous resources
|
||||
};
|
||||
|
||||
|
||||
#endif // nsRDFContentSink_h__
|
||||
759
mozilla/rdf/base/src/nsRDFService.cpp
Normal file
759
mozilla/rdf/base/src/nsRDFService.cpp
Normal file
@@ -0,0 +1,759 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file provides the implementation for the RDF service manager.
|
||||
|
||||
TO DO
|
||||
-----
|
||||
|
||||
1) Figure out a better way to do "pluggable resources." Currently,
|
||||
we have two _major_ hacks:
|
||||
|
||||
RegisterBuiltInNamedDataSources()
|
||||
RegisterBuiltInResourceFactories()
|
||||
|
||||
These introduce dependencies on the datasource directory. You'd
|
||||
like to have this stuff discovered dynamically at startup or
|
||||
something. Maybe from the registry.
|
||||
|
||||
2) Implement the CreateDataBase() methods.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFResourceFactory.h"
|
||||
#include "nsString.h"
|
||||
#include "plhash.h"
|
||||
#include "plstr.h"
|
||||
#include "prlog.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// PrefixMap
|
||||
//
|
||||
// A simple map from a string prefix to a value. It maintains an
|
||||
// ordered list of prefixes that map to a <tt>void*</tt>. The list
|
||||
// is sorted in ASCII order such that if one prefix <b>p</b> is
|
||||
// itself a prefix of another prefix <b>q</b>, the longest prefix
|
||||
// (<b>q</b>) will appear first in the list. The idea is that you
|
||||
// want to find the "best" match first. (Will this actually be
|
||||
// useful? Probabably not...)
|
||||
//
|
||||
class PrefixMap
|
||||
{
|
||||
private:
|
||||
struct PrefixMapEntry
|
||||
{
|
||||
const char* mPrefix;
|
||||
PRInt32 mPrefixLen;
|
||||
const void* mValue;
|
||||
PrefixMapEntry* mNext;
|
||||
};
|
||||
|
||||
PrefixMapEntry* mHead;
|
||||
|
||||
public:
|
||||
PrefixMap();
|
||||
~PrefixMap();
|
||||
|
||||
PRBool Add(const char* aPrefix, const void* aValue);
|
||||
const void* Remove(const char* aPrefix);
|
||||
|
||||
/**
|
||||
* Find the most specific value matching the specified string.
|
||||
*/
|
||||
const void* Find(const char* aString);
|
||||
};
|
||||
|
||||
|
||||
PrefixMap::PrefixMap()
|
||||
: mHead(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
PrefixMap::~PrefixMap()
|
||||
{
|
||||
while (mHead) {
|
||||
PrefixMapEntry* doomed = mHead;
|
||||
mHead = mHead->mNext;
|
||||
PL_strfree(NS_CONST_CAST(char*, doomed->mPrefix));
|
||||
delete doomed;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
PrefixMap::Add(const char* aPrefix, const void* aValue)
|
||||
{
|
||||
PRInt32 newPrefixLen = PL_strlen(aPrefix);
|
||||
PrefixMapEntry* entry = mHead;
|
||||
PrefixMapEntry* last = nsnull;
|
||||
|
||||
while (entry != nsnull) {
|
||||
// check to see if the new prefix is longer than the current
|
||||
// entry. If so, we'll want to insert the new prefix *before*
|
||||
// this one.
|
||||
if (newPrefixLen > entry->mPrefixLen)
|
||||
break;
|
||||
|
||||
// check for exact equality: if so, the prefix is already
|
||||
// registered, so fail (?)
|
||||
if (PL_strcmp(entry->mPrefix, aPrefix) == 0)
|
||||
return PR_FALSE;
|
||||
|
||||
// otherwise, the new prefix is the same length or shorter
|
||||
// than the current entry: continue on to the next one.
|
||||
|
||||
last = entry;
|
||||
entry = entry->mNext;
|
||||
}
|
||||
|
||||
PrefixMapEntry* newEntry = new PrefixMapEntry;
|
||||
if (! newEntry)
|
||||
return PR_FALSE;
|
||||
|
||||
|
||||
newEntry->mPrefix = PL_strdup(aPrefix);
|
||||
newEntry->mPrefixLen = newPrefixLen;
|
||||
newEntry->mValue = aValue;
|
||||
|
||||
if (last) {
|
||||
// we found an entry that we need to insert the current
|
||||
// entry *before*
|
||||
newEntry->mNext = last->mNext;
|
||||
last->mNext = newEntry;
|
||||
}
|
||||
else {
|
||||
// Otherwise, insert at the start
|
||||
newEntry->mNext = mHead;
|
||||
mHead = newEntry;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
const void*
|
||||
PrefixMap::Remove(const char* aPrefix)
|
||||
{
|
||||
PrefixMapEntry* entry = mHead;
|
||||
PrefixMapEntry* last = nsnull;
|
||||
|
||||
PRInt32 doomedPrefixLen = PL_strlen(aPrefix);
|
||||
|
||||
while (entry != nsnull) {
|
||||
if ((doomedPrefixLen == entry->mPrefixLen) &&
|
||||
(PL_strcmp(entry->mPrefix, aPrefix) == 0)) {
|
||||
if (last) {
|
||||
last->mNext = entry->mNext;
|
||||
}
|
||||
else {
|
||||
mHead = entry->mNext;
|
||||
}
|
||||
|
||||
const void* value = entry->mValue;
|
||||
|
||||
PL_strfree(NS_CONST_CAST(char*, entry->mPrefix));
|
||||
delete entry;
|
||||
|
||||
return value;
|
||||
}
|
||||
last = entry;
|
||||
entry = entry->mNext;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
const void*
|
||||
PrefixMap::Find(const char* aString)
|
||||
{
|
||||
for (PrefixMapEntry* entry = mHead; entry != nsnull; entry = entry->mNext) {
|
||||
PRInt32 cmp = PL_strncmp(entry->mPrefix, aString, entry->mPrefixLen);
|
||||
if (cmp == 0)
|
||||
return entry->mValue;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// LiteralImpl
|
||||
//
|
||||
// Currently, all literals are implemented exactly the same way;
|
||||
// i.e., there is are no resource factories to allow you to generate
|
||||
// customer resources. I doubt that makes sense, anyway.
|
||||
//
|
||||
// What _may_ make sense is to atomize literals (well, at least
|
||||
// short ones), to reduce in memory overhead at the expense of some
|
||||
// processing time.
|
||||
//
|
||||
class LiteralImpl : public nsIRDFLiteral {
|
||||
public:
|
||||
LiteralImpl(const PRUnichar* s);
|
||||
virtual ~LiteralImpl(void);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFNode
|
||||
NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const;
|
||||
|
||||
// nsIRDFLiteral
|
||||
NS_IMETHOD GetValue(const PRUnichar* *value) const;
|
||||
NS_IMETHOD EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const;
|
||||
|
||||
private:
|
||||
nsAutoString mValue;
|
||||
};
|
||||
|
||||
|
||||
LiteralImpl::LiteralImpl(const PRUnichar* s)
|
||||
: mValue(s)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
LiteralImpl::~LiteralImpl(void)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(LiteralImpl);
|
||||
NS_IMPL_RELEASE(LiteralImpl);
|
||||
|
||||
nsresult
|
||||
LiteralImpl::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = nsnull;
|
||||
if (iid.Equals(kIRDFLiteralIID) ||
|
||||
iid.Equals(kIRDFNodeIID) ||
|
||||
iid.Equals(kISupportsIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFLiteral*, this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LiteralImpl::EqualsNode(nsIRDFNode* node, PRBool* result) const
|
||||
{
|
||||
nsresult rv;
|
||||
nsIRDFLiteral* literal;
|
||||
if (NS_SUCCEEDED(node->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
|
||||
rv = EqualsLiteral(literal, result);
|
||||
NS_RELEASE(literal);
|
||||
}
|
||||
else {
|
||||
*result = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LiteralImpl::GetValue(const PRUnichar* *value) const
|
||||
{
|
||||
NS_ASSERTION(value, "null ptr");
|
||||
if (! value)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*value = mValue.GetUnicode();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
LiteralImpl::EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const
|
||||
{
|
||||
NS_ASSERTION(literal && result, "null ptr");
|
||||
if (!literal || !result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
const PRUnichar* p;
|
||||
if (NS_FAILED(rv = literal->GetValue(&p)))
|
||||
return rv;
|
||||
|
||||
nsAutoString s(p);
|
||||
|
||||
*result = s.Equals(mValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ServiceImpl
|
||||
//
|
||||
// This is the RDF service.
|
||||
//
|
||||
class ServiceImpl : public nsIRDFService
|
||||
{
|
||||
protected:
|
||||
PrefixMap mResourceFactories;
|
||||
PLHashTable* mNamedDataSources;
|
||||
PLHashTable* mDataSourceConstructors;
|
||||
PLHashTable* mResources;
|
||||
|
||||
ServiceImpl(void);
|
||||
virtual ~ServiceImpl(void);
|
||||
|
||||
static nsIRDFService* gRDFService; // The one-and-only RDF service
|
||||
|
||||
static void RegisterBuiltInResourceFactories();
|
||||
static void RegisterBuiltInNamedDataSources();
|
||||
|
||||
public:
|
||||
|
||||
static nsresult GetRDFService(nsIRDFService** result);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFService
|
||||
NS_IMETHOD GetResource(const char* uri, nsIRDFResource** resource);
|
||||
NS_IMETHOD GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource);
|
||||
NS_IMETHOD GetLiteral(const PRUnichar* value, nsIRDFLiteral** literal);
|
||||
NS_IMETHOD UnCacheResource(nsIRDFResource* resource);
|
||||
|
||||
NS_IMETHOD RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory);
|
||||
NS_IMETHOD UnRegisterResourceFactory(const char* aURIPrefix);
|
||||
|
||||
NS_IMETHOD RegisterDataSource(nsIRDFDataSource* dataSource);
|
||||
NS_IMETHOD UnregisterDataSource(nsIRDFDataSource* dataSource);
|
||||
NS_IMETHOD RegisterDataSourceConstructor(const char* uri, NSDataSourceConstructorCallback fn);
|
||||
NS_IMETHOD UnregisterDataSourceConstructor(const char* uri);
|
||||
NS_IMETHOD GetDataSource(const char* uri, nsIRDFDataSource** dataSource);
|
||||
NS_IMETHOD CreateDatabase(const char** uris, nsIRDFDataBase** dataBase);
|
||||
NS_IMETHOD CreateBrowserDatabase(nsIRDFDataBase** dataBase);
|
||||
};
|
||||
|
||||
nsIRDFService* ServiceImpl::gRDFService = nsnull;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ServiceImpl::ServiceImpl(void)
|
||||
: mResources(nsnull), mNamedDataSources(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mResources = PL_NewHashTable(1023, // nbuckets
|
||||
PL_HashString, // hash fn
|
||||
PL_CompareStrings, // key compare fn
|
||||
PL_CompareValues, // value compare fn
|
||||
nsnull, nsnull); // alloc ops & priv
|
||||
|
||||
mNamedDataSources = PL_NewHashTable(23,
|
||||
PL_HashString,
|
||||
PL_CompareStrings,
|
||||
PL_CompareValues,
|
||||
nsnull, nsnull);
|
||||
|
||||
mDataSourceConstructors = PL_NewHashTable(23,
|
||||
PL_HashString,
|
||||
PL_CompareStrings,
|
||||
PL_CompareValues,
|
||||
nsnull, nsnull);
|
||||
}
|
||||
|
||||
|
||||
ServiceImpl::~ServiceImpl(void)
|
||||
{
|
||||
if (mDataSourceConstructors) {
|
||||
PL_HashTableDestroy(mDataSourceConstructors);
|
||||
mDataSourceConstructors = nsnull;
|
||||
}
|
||||
if (mNamedDataSources) {
|
||||
PL_HashTableDestroy(mNamedDataSources);
|
||||
mNamedDataSources = nsnull;
|
||||
}
|
||||
if (mResources) {
|
||||
PL_HashTableDestroy(mResources);
|
||||
mResources = nsnull;
|
||||
}
|
||||
gRDFService = nsnull;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
ServiceImpl::GetRDFService(nsIRDFService** mgr)
|
||||
{
|
||||
if (! gRDFService) {
|
||||
gRDFService = new ServiceImpl();
|
||||
if (! gRDFService)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
RegisterBuiltInResourceFactories();
|
||||
RegisterBuiltInNamedDataSources();
|
||||
}
|
||||
|
||||
NS_ADDREF(gRDFService);
|
||||
*mgr = gRDFService;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
ServiceImpl::AddRef(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
ServiceImpl::Release(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE(ServiceImpl, kIRDFServiceIID);
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::GetResource(const char* uri, nsIRDFResource** resource)
|
||||
{
|
||||
nsIRDFResource* result =
|
||||
NS_STATIC_CAST(nsIRDFResource*, PL_HashTableLookup(mResources, uri));
|
||||
|
||||
if (! result) {
|
||||
nsIRDFResourceFactory* factory =
|
||||
NS_STATIC_CAST(nsIRDFResourceFactory*,
|
||||
NS_CONST_CAST(void*, mResourceFactories.Find(uri)));
|
||||
|
||||
PR_ASSERT(factory != nsnull);
|
||||
if (! factory)
|
||||
return NS_ERROR_FAILURE; // XXX
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(rv = factory->CreateResource(uri, &result)))
|
||||
return rv;
|
||||
|
||||
const char* uri;
|
||||
result->GetValue(&uri);
|
||||
|
||||
// This is a little trick to make storage more efficient. For
|
||||
// the "key" in the table, we'll use the string value that's
|
||||
// stored as a member variable of the nsIRDFResource object.
|
||||
PL_HashTableAdd(mResources, uri, result);
|
||||
|
||||
// *We* don't AddRef() the resource: that way, the resource
|
||||
// can be garbage collected when the last refcount goes
|
||||
// away. The single addref that the CreateResource() call made
|
||||
// will be owned by the callee.
|
||||
}
|
||||
else {
|
||||
// Addref for the callee.
|
||||
NS_ADDREF(result);
|
||||
}
|
||||
|
||||
*resource = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource)
|
||||
{
|
||||
nsString s(uri);
|
||||
char* cstr = s.ToNewCString();
|
||||
nsresult rv = GetResource(cstr, resource);
|
||||
delete[] cstr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::GetLiteral(const PRUnichar* uri, nsIRDFLiteral** literal)
|
||||
{
|
||||
LiteralImpl* result = new LiteralImpl(uri);
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*literal = result;
|
||||
NS_ADDREF(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::UnCacheResource(nsIRDFResource* resource)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
const char* uri;
|
||||
if (NS_FAILED(rv = resource->GetValue(&uri)))
|
||||
return rv;
|
||||
|
||||
PL_HashTableRemove(mResources, uri);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory)
|
||||
{
|
||||
if (! mResourceFactories.Add(aURIPrefix, aFactory))
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
NS_ADDREF(aFactory); // XXX should we addref?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::UnRegisterResourceFactory(const char* aURIPrefix)
|
||||
{
|
||||
nsIRDFResourceFactory* factory =
|
||||
NS_STATIC_CAST(nsIRDFResourceFactory*,
|
||||
NS_CONST_CAST(void*, mResourceFactories.Remove(aURIPrefix)));
|
||||
|
||||
if (! factory)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
NS_RELEASE(factory); // XXX should we addref?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
const char* uri;
|
||||
if (NS_FAILED(rv = aDataSource->GetURI(&uri)))
|
||||
return rv;
|
||||
|
||||
// XXX check for dups, etc.
|
||||
|
||||
PL_HashTableAdd(mNamedDataSources, uri, aDataSource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
const char* uri;
|
||||
if (NS_FAILED(rv = aDataSource->GetURI(&uri)))
|
||||
return rv;
|
||||
|
||||
nsIRDFDataSource* ds =
|
||||
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
|
||||
|
||||
if (! ds)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
PL_HashTableRemove(mNamedDataSources, uri);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::RegisterDataSourceConstructor(const char* uri, NSDataSourceConstructorCallback fn)
|
||||
{
|
||||
// XXX check for dups, etc.
|
||||
PL_HashTableAdd(mDataSourceConstructors, uri, fn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::UnregisterDataSourceConstructor(const char* uri)
|
||||
{
|
||||
PL_HashTableRemove(mDataSourceConstructors, uri);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::GetDataSource(const char* uri, nsIRDFDataSource** aDataSource)
|
||||
{
|
||||
nsIRDFDataSource* ds =
|
||||
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
|
||||
|
||||
if (ds) {
|
||||
NS_ADDREF(ds);
|
||||
*aDataSource = ds;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise, see if we have a lazy constructor
|
||||
NSDataSourceConstructorCallback constructor =
|
||||
(NSDataSourceConstructorCallback)
|
||||
PL_HashTableLookup(mDataSourceConstructors, uri);
|
||||
|
||||
if (constructor) {
|
||||
// Yep, so try to construct it on the fly...
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(rv = constructor(&ds))) {
|
||||
#ifdef DEBUG
|
||||
printf("error constructing built-in datasource %s\n", uri);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If it wants to register itself, it should do so in the Init() method.
|
||||
if (NS_FAILED(rv = ds->Init(uri))) {
|
||||
#ifdef DEBUG
|
||||
printf("error initializing named datasource %s\n", uri);
|
||||
#endif
|
||||
NS_RELEASE(ds);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// constructor did an implicit addref
|
||||
*aDataSource = ds;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX at this point, we might want to try to construct a
|
||||
// stream URI and load it that way...
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::CreateDatabase(const char** uri, nsIRDFDataBase** dataBase)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceImpl::CreateBrowserDatabase(nsIRDFDataBase** dataBase)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is Big Hack #1. Depedencies on all builtin resource
|
||||
// factories are *here*, in the ResourceFactoryTable.
|
||||
//
|
||||
|
||||
struct ResourceFactoryTable {
|
||||
const char* mPrefix;
|
||||
nsresult (*mFactoryConstructor)(nsIRDFResourceFactory** result);
|
||||
};
|
||||
|
||||
void
|
||||
ServiceImpl::RegisterBuiltInResourceFactories(void)
|
||||
{
|
||||
extern nsresult NS_NewRDFDefaultResourceFactory(nsIRDFResourceFactory** result);
|
||||
extern nsresult NS_NewRDFMailResourceFactory(nsIRDFResourceFactory** result);
|
||||
extern nsresult NS_NewRDFMailAccountResourceFactory(nsIRDFResourceFactory** result);
|
||||
extern nsresult NS_NewRDFFileResourceFactory(nsIRDFResourceFactory** result);
|
||||
|
||||
static ResourceFactoryTable gTable[] = {
|
||||
"", NS_NewRDFDefaultResourceFactory,
|
||||
"mailaccount:", NS_NewRDFMailAccountResourceFactory,
|
||||
"mailbox:", NS_NewRDFMailResourceFactory,
|
||||
#if 0
|
||||
"file:", NS_NewRDFFileResourceFactory,
|
||||
#endif
|
||||
nsnull, nsnull
|
||||
};
|
||||
|
||||
nsresult rv;
|
||||
for (ResourceFactoryTable* entry = gTable; entry->mPrefix != nsnull; ++entry) {
|
||||
nsIRDFResourceFactory* factory;
|
||||
|
||||
if (NS_FAILED(rv = (entry->mFactoryConstructor)(&factory)))
|
||||
continue;
|
||||
|
||||
rv = gRDFService->RegisterResourceFactory(entry->mPrefix, factory);
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
NS_RELEASE(factory);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is Big Hack #2. Dependencies on all builtin datasources are
|
||||
// *here*, in the DataSourceTable.
|
||||
//
|
||||
// FWIW, I don't particularly like this interface *anyway*, because
|
||||
// it requires each built-in data source to be constructed "up
|
||||
// front". Not only does it cause the service manager to be
|
||||
// re-entered (which may be a problem), but it's wasteful: I think
|
||||
// these data sources should be created on demand, and released when
|
||||
// you're done with them.
|
||||
//
|
||||
|
||||
struct DataSourceTable {
|
||||
const char* mURI;
|
||||
nsresult (*mDataSourceConstructor)(nsIRDFDataSource** result);
|
||||
};
|
||||
|
||||
void
|
||||
ServiceImpl::RegisterBuiltInNamedDataSources(void)
|
||||
{
|
||||
extern nsresult NS_NewRDFBookmarkDataSource(nsIRDFDataSource** result);
|
||||
extern nsresult NS_NewRDFHistoryDataSource(nsIRDFDataSource** result);
|
||||
extern nsresult NS_NewRDFLocalFileSystemDataSource(nsIRDFDataSource** result);
|
||||
extern nsresult NS_NewRDFMailDataSource(nsIRDFDataSource** result);
|
||||
|
||||
static DataSourceTable gTable[] = {
|
||||
"rdf:bookmarks", NS_NewRDFBookmarkDataSource,
|
||||
"rdf:mail", NS_NewRDFMailDataSource,
|
||||
#if 0
|
||||
"rdf:history", NS_NewRDFHistoryDataSource,
|
||||
"rdf:lfs", NS_NewRDFLocalFileSystemDataSource,
|
||||
#endif
|
||||
nsnull, nsnull
|
||||
};
|
||||
|
||||
nsresult rv;
|
||||
for (DataSourceTable* entry = gTable; entry->mURI != nsnull; ++entry) {
|
||||
if (NS_FAILED(rv = gRDFService->RegisterDataSourceConstructor(entry->mURI, entry->mDataSourceConstructor))) {
|
||||
#ifdef DEBUG
|
||||
printf("error registering built-in datasource constructor for %s\n", entry->mURI);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFService(nsIRDFService** mgr)
|
||||
{
|
||||
return ServiceImpl::GetRDFService(mgr);
|
||||
}
|
||||
837
mozilla/rdf/base/src/nsRDFXMLDataSource.cpp
Normal file
837
mozilla/rdf/base/src/nsRDFXMLDataSource.cpp
Normal file
@@ -0,0 +1,837 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A data source that can read itself from and write itself to an
|
||||
RDF/XML stream.
|
||||
|
||||
TO DO
|
||||
-----
|
||||
|
||||
1) Right now, the only kind of stream data sources that are writable
|
||||
are "file:" URIs. (In fact, <em>all</em> "file:" URIs are
|
||||
writable, modulo flie system permissions; this may lead to some
|
||||
surprising behavior.) Eventually, it'd be great if we could open
|
||||
an arbitrary nsIOutputStream on *any* URL, and Netlib could just
|
||||
do the magic.
|
||||
|
||||
2) We need a way to decide whether or not the stream should be read
|
||||
with a blocking read or an asynchronous read. This issue is
|
||||
particularly important for consumers that expect to be able to
|
||||
Init() a data source and then have it be 100% ready for use
|
||||
(e.g., the regsitry). Does this warrant a new interface? Right
|
||||
now, we just assume that "file:" and "resource:" URIs should be
|
||||
read synchronously.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsIDTD.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIParser.h"
|
||||
#include "nsIRDFContentSink.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFXMLDataSource.h"
|
||||
#include "nsIRDFXMLSource.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsLayoutCID.h" // for NS_NAMESPACEMANAGER_CID.
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "plstr.h"
|
||||
#include "prio.h"
|
||||
#include "prthread.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
|
||||
static NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
|
||||
static NS_DEFINE_IID(kINameSpaceManagerIID, NS_INAMESPACEMANAGER_IID);
|
||||
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
|
||||
static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID);
|
||||
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFContentSinkIID, NS_IRDFCONTENTSINK_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_IID(kIRDFXMLDataSourceIID, NS_IRDFXMLDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFXMLSourceIID, NS_IRDFXMLSOURCE_IID);
|
||||
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); // XXX
|
||||
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FileOutputStreamImpl
|
||||
|
||||
class FileOutputStreamImpl : public nsIOutputStream
|
||||
{
|
||||
private:
|
||||
nsOutputFileStream mStream;
|
||||
|
||||
public:
|
||||
FileOutputStreamImpl(const nsFilePath& path)
|
||||
: mStream(path)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
virtual ~FileOutputStreamImpl(void) {
|
||||
Close();
|
||||
}
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIBaseStream interface
|
||||
NS_IMETHOD Close(void) {
|
||||
mStream.close();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIOutputStream interface
|
||||
NS_IMETHOD Write(const char* aBuf,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount,
|
||||
PRUint32 *aWriteCount)
|
||||
{
|
||||
PRInt32 written = mStream.write(aBuf + aOffset, aCount);
|
||||
if (written == -1) {
|
||||
*aWriteCount = 0;
|
||||
return NS_ERROR_FAILURE; // XXX right error code?
|
||||
}
|
||||
else {
|
||||
*aWriteCount = written;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FileOutputStreamImpl, kIOutputStreamIID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ProxyStream : public nsIInputStream
|
||||
{
|
||||
private:
|
||||
const char* mBuffer;
|
||||
PRUint32 mSize;
|
||||
PRUint32 mIndex;
|
||||
|
||||
public:
|
||||
ProxyStream(void) : mBuffer(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
virtual ~ProxyStream(void) {
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIBaseStream
|
||||
NS_IMETHOD Close(void) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInputStream
|
||||
NS_IMETHOD GetLength(PRUint32 *aLength) {
|
||||
*aLength = mSize - mIndex;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD Read(char* aBuf, PRUint32 aOffset, PRUint32 aCount, PRUint32 *aReadCount) {
|
||||
PRUint32 readCount = 0;
|
||||
aBuf += aOffset;
|
||||
while (mIndex < mSize && aCount > 0) {
|
||||
*aBuf = mBuffer[mIndex];
|
||||
aBuf++;
|
||||
mIndex++;
|
||||
readCount++;
|
||||
aCount--;
|
||||
}
|
||||
*aReadCount = readCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Implementation
|
||||
void SetBuffer(const char* aBuffer, PRUint32 aSize) {
|
||||
mBuffer = aBuffer;
|
||||
mSize = aSize;
|
||||
mIndex = 0;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ProxyStream, kIInputStreamIID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// RDFXMLDataSourceImpl
|
||||
|
||||
class RDFXMLDataSourceImpl : public nsIRDFXMLDataSource,
|
||||
public nsIRDFXMLSource
|
||||
{
|
||||
protected:
|
||||
nsIRDFDataSource* mInner;
|
||||
PRBool mIsSynchronous; // true if the document should be loaded synchronously
|
||||
PRBool mIsWritable; // true if the document can be written back
|
||||
PRBool mIsDirty; // true if the document should be written back
|
||||
nsVoidArray mObservers;
|
||||
char** mNamedDataSourceURIs;
|
||||
PRInt32 mNumNamedDataSourceURIs;
|
||||
nsIURL** mCSSStyleSheetURLs;
|
||||
PRInt32 mNumCSSStyleSheetURLs;
|
||||
nsIRDFResource* mRootResource;
|
||||
PRBool mIsLoading; // true while the document is loading
|
||||
|
||||
public:
|
||||
RDFXMLDataSourceImpl(void);
|
||||
virtual ~RDFXMLDataSourceImpl(void);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFDataSource
|
||||
NS_IMETHOD Init(const char* uri);
|
||||
|
||||
NS_IMETHOD GetURI(const char* *uri) const {
|
||||
return mInner->GetURI(uri);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source) {
|
||||
return mInner->GetSource(property, target, tv, source);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** sources) {
|
||||
return mInner->GetSources(property, target, tv, sources);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target) {
|
||||
return mInner->GetTarget(source, property, tv, target);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** targets) {
|
||||
return mInner->GetTargets(source, property, tv, targets);
|
||||
}
|
||||
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv);
|
||||
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target);
|
||||
|
||||
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion) {
|
||||
return mInner->HasAssertion(source, property, target, tv, hasAssertion);
|
||||
}
|
||||
|
||||
NS_IMETHOD AddObserver(nsIRDFObserver* n) {
|
||||
return mInner->AddObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) {
|
||||
return mInner->RemoveObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels) {
|
||||
return mInner->ArcLabelsIn(node, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels) {
|
||||
return mInner->ArcLabelsOut(source, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush(void);
|
||||
|
||||
NS_IMETHOD IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult) {
|
||||
return mInner->IsCommandEnabled(aCommand, aCommandTarget, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHOD DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget) {
|
||||
// XXX Uh oh, this could cause problems wrt. the "dirty" flag
|
||||
// if it changes the in-memory store's internal state.
|
||||
return mInner->DoCommand(aCommand, aCommandTarget);
|
||||
}
|
||||
|
||||
// nsIRDFXMLDataSource interface
|
||||
NS_IMETHOD SetSynchronous(PRBool aIsSynchronous);
|
||||
NS_IMETHOD SetReadOnly(PRBool aIsReadOnly);
|
||||
NS_IMETHOD BeginLoad(void);
|
||||
NS_IMETHOD Interrupt(void);
|
||||
NS_IMETHOD Resume(void);
|
||||
NS_IMETHOD EndLoad(void);
|
||||
NS_IMETHOD SetRootResource(nsIRDFResource* aResource);
|
||||
NS_IMETHOD GetRootResource(nsIRDFResource** aResource);
|
||||
NS_IMETHOD AddCSSStyleSheetURL(nsIURL* aStyleSheetURL);
|
||||
NS_IMETHOD GetCSSStyleSheetURLs(nsIURL*** aStyleSheetURLs, PRInt32* aCount);
|
||||
NS_IMETHOD AddNamedDataSourceURI(const char* aNamedDataSourceURI);
|
||||
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount);
|
||||
NS_IMETHOD AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
|
||||
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver);
|
||||
|
||||
// nsIRDFXMLSource interface
|
||||
NS_IMETHOD Serialize(nsIOutputStream* aStream);
|
||||
|
||||
// Implementation methods
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFXMLDataSource(nsIRDFXMLDataSource** result)
|
||||
{
|
||||
RDFXMLDataSourceImpl* ds = new RDFXMLDataSourceImpl();
|
||||
if (! ds)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = ds;
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
|
||||
: mIsSynchronous(PR_FALSE),
|
||||
mIsWritable(PR_TRUE),
|
||||
mIsDirty(PR_FALSE),
|
||||
mNamedDataSourceURIs(nsnull),
|
||||
mNumNamedDataSourceURIs(0),
|
||||
mCSSStyleSheetURLs(nsnull),
|
||||
mNumCSSStyleSheetURLs(0),
|
||||
mIsLoading(PR_FALSE)
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFInMemoryDataSourceCID,
|
||||
nsnull,
|
||||
kIRDFDataSourceIID,
|
||||
(void**) &mInner)))
|
||||
PR_ASSERT(0);
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void)
|
||||
{
|
||||
nsIRDFService* rdfService;
|
||||
if (NS_SUCCEEDED(nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &rdfService))) {
|
||||
rdfService->UnregisterDataSource(this);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
||||
}
|
||||
|
||||
Flush();
|
||||
|
||||
while (--mNumNamedDataSourceURIs >= 0)
|
||||
delete mNamedDataSourceURIs[mNumNamedDataSourceURIs];
|
||||
|
||||
delete mNamedDataSourceURIs;
|
||||
|
||||
while (--mNumCSSStyleSheetURLs >= 0)
|
||||
NS_RELEASE(mCSSStyleSheetURLs[mNumCSSStyleSheetURLs]);
|
||||
|
||||
delete mCSSStyleSheetURLs;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(RDFXMLDataSourceImpl);
|
||||
NS_IMPL_RELEASE(RDFXMLDataSourceImpl);
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (iid.Equals(kISupportsIID) ||
|
||||
iid.Equals(kIRDFDataSourceIID) ||
|
||||
iid.Equals(kIRDFXMLDataSourceIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFDataSource*, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
else if (iid.Equals(kIRDFXMLSourceIID)) {
|
||||
*result = NS_STATIC_CAST(nsIRDFXMLSource*, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
*result = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
rdf_BlockingParse(nsIURL* aURL, nsIStreamListener* aConsumer)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// XXX I really hate the way that we're spoon-feeding this stuff
|
||||
// to the parser: it seems like this is something that netlib
|
||||
// should be able to do by itself.
|
||||
|
||||
nsIInputStream* in;
|
||||
if (NS_FAILED(rv = NS_OpenURL(aURL, &in, nsnull /* XXX aConsumer */)))
|
||||
return rv;
|
||||
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
ProxyStream* proxy = new ProxyStream();
|
||||
if (! proxy)
|
||||
goto done;
|
||||
|
||||
// XXX shouldn't netlib be doing this???
|
||||
aConsumer->OnStartBinding(aURL, "text/rdf");
|
||||
while (PR_TRUE) {
|
||||
char buf[1024];
|
||||
PRUint32 readCount;
|
||||
|
||||
if (NS_FAILED(rv = in->Read(buf, 0, sizeof(buf), &readCount)))
|
||||
break; // error or eof
|
||||
|
||||
if (readCount == 0)
|
||||
break; // eof
|
||||
|
||||
proxy->SetBuffer(buf, readCount);
|
||||
|
||||
// XXX shouldn't netlib be doing this???
|
||||
if (NS_FAILED(rv = aConsumer->OnDataAvailable(aURL, proxy, readCount)))
|
||||
break;
|
||||
}
|
||||
if (rv == NS_BASE_STREAM_EOF) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
// XXX shouldn't netlib be doing this???
|
||||
aConsumer->OnStopBinding(aURL, 0, nsnull);
|
||||
|
||||
done:
|
||||
NS_RELEASE(in);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Init(const char* uri)
|
||||
{
|
||||
static const char kFileURIPrefix[] = "file:";
|
||||
static const char kResourceURIPrefix[] = "resource:";
|
||||
|
||||
NS_PRECONDITION(mInner != nsnull, "not initialized");
|
||||
if (! mInner)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXX this is a hack: any "file:" URI is considered writable. All
|
||||
// others are considered read-only.
|
||||
if (PL_strncmp(uri, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0)
|
||||
mIsWritable = PR_FALSE;
|
||||
|
||||
nsIRDFService* rdfService = nsnull;
|
||||
nsINameSpaceManager* ns = nsnull;
|
||||
nsIRDFContentSink* sink = nsnull;
|
||||
nsIParser* parser = nsnull;
|
||||
nsIDTD* dtd = nsnull;
|
||||
nsIStreamListener* lsnr = nsnull;
|
||||
nsIURL* url = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewURL(&url, uri)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = mInner->Init(uri)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &rdfService)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = rdfService->RegisterDataSource(this)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kNameSpaceManagerCID,
|
||||
nsnull,
|
||||
kINameSpaceManagerIID,
|
||||
(void**) &ns)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFContentSinkCID,
|
||||
nsnull,
|
||||
kIRDFContentSinkIID,
|
||||
(void**) &sink)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(sink->Init(url, ns)))
|
||||
goto done;
|
||||
|
||||
// We set the content sink's data source directly to our in-memory
|
||||
// store. This allows the initial content to be generated "directly".
|
||||
if (NS_FAILED(rv = sink->SetDataSource(this)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kParserCID,
|
||||
nsnull,
|
||||
kIParserIID,
|
||||
(void**) &parser)))
|
||||
goto done;
|
||||
|
||||
parser->SetContentSink(sink);
|
||||
|
||||
// XXX this should eventually be kRDFDTDCID (oh boy, that's a
|
||||
// pretty identifier). The RDF DTD will be a much more
|
||||
// RDF-resilient parser.
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kWellFormedDTDCID,
|
||||
nsnull,
|
||||
kIDTDIID,
|
||||
(void**) &dtd)))
|
||||
goto done;
|
||||
|
||||
parser->RegisterDTD(dtd);
|
||||
|
||||
if (NS_FAILED(rv = parser->QueryInterface(kIStreamListenerIID, (void**) &lsnr)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(parser->Parse(url)))
|
||||
goto done;
|
||||
|
||||
// XXX Yet another hack to get the registry stuff
|
||||
// bootstrapped. Force "file:" and "resource:" URIs to be loaded
|
||||
// by a blocking read. Maybe there needs to be a distinct
|
||||
// interface for stream data sources?
|
||||
if (mIsSynchronous) {
|
||||
rv = rdf_BlockingParse(url, lsnr);
|
||||
}
|
||||
else {
|
||||
rv = NS_OpenURL(url, lsnr);
|
||||
}
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(lsnr);
|
||||
NS_IF_RELEASE(dtd);
|
||||
NS_IF_RELEASE(parser);
|
||||
NS_IF_RELEASE(sink);
|
||||
if (rdfService) {
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
||||
rdfService = nsnull;
|
||||
}
|
||||
NS_IF_RELEASE(url);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv)
|
||||
{
|
||||
if (!mIsLoading && !mIsWritable)
|
||||
return NS_ERROR_FAILURE; // XXX right error code?
|
||||
|
||||
nsresult rv;
|
||||
if (NS_SUCCEEDED(rv = mInner->Assert(source, property, target, tv))) {
|
||||
if (!mIsLoading)
|
||||
mIsDirty = PR_TRUE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target)
|
||||
{
|
||||
if (!mIsLoading && !mIsWritable)
|
||||
return NS_ERROR_FAILURE; // XXX right error code?
|
||||
|
||||
nsresult rv;
|
||||
if (NS_SUCCEEDED(rv = mInner->Unassert(source, property, target))) {
|
||||
if (!mIsLoading)
|
||||
mIsDirty = PR_TRUE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Flush(void)
|
||||
{
|
||||
if (!mIsWritable || !mIsDirty)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
const char* uri;
|
||||
if (NS_FAILED(rv = mInner->GetURI(&uri)))
|
||||
return rv;
|
||||
|
||||
nsFileURL url(uri);
|
||||
nsFilePath path(url);
|
||||
|
||||
FileOutputStreamImpl* out = new FileOutputStreamImpl(path);
|
||||
if (! out)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (NS_FAILED(rv = Serialize(out)))
|
||||
goto done;
|
||||
|
||||
mIsDirty = PR_FALSE;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(out);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFXMLDataSource methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetSynchronous(PRBool aIsSynchronous)
|
||||
{
|
||||
mIsSynchronous = aIsSynchronous;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetReadOnly(PRBool aIsReadOnly)
|
||||
{
|
||||
if (mIsWritable && aIsReadOnly)
|
||||
mIsWritable = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::BeginLoad(void)
|
||||
{
|
||||
mIsLoading = PR_TRUE;
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnBeginLoad(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Interrupt(void)
|
||||
{
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnInterrupt(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Resume(void)
|
||||
{
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnResume(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::EndLoad(void)
|
||||
{
|
||||
mIsLoading = PR_FALSE;
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnEndLoad(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::SetRootResource(nsIRDFResource* aResource)
|
||||
{
|
||||
NS_PRECONDITION(aResource != nsnull, "null ptr");
|
||||
if (! aResource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_ADDREF(aResource);
|
||||
mRootResource = aResource;
|
||||
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnRootResourceFound(this, mRootResource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetRootResource(nsIRDFResource** aResource)
|
||||
{
|
||||
NS_ADDREF(mRootResource);
|
||||
*aResource = mRootResource;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddCSSStyleSheetURL(nsIURL* aCSSStyleSheetURL)
|
||||
{
|
||||
NS_PRECONDITION(aCSSStyleSheetURL != nsnull, "null ptr");
|
||||
if (! aCSSStyleSheetURL)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIURL** p = new nsIURL*[mNumCSSStyleSheetURLs + 1];
|
||||
if (! p)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PRInt32 i;
|
||||
for (i = mNumCSSStyleSheetURLs - 1; i >= 0; --i)
|
||||
p[i] = mCSSStyleSheetURLs[i];
|
||||
|
||||
NS_ADDREF(aCSSStyleSheetURL);
|
||||
p[mNumCSSStyleSheetURLs] = aCSSStyleSheetURL;
|
||||
|
||||
++mNumCSSStyleSheetURLs;
|
||||
mCSSStyleSheetURLs = p;
|
||||
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnCSSStyleSheetAdded(this, aCSSStyleSheetURL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetCSSStyleSheetURLs(nsIURL*** aCSSStyleSheetURLs, PRInt32* aCount)
|
||||
{
|
||||
*aCSSStyleSheetURLs = mCSSStyleSheetURLs;
|
||||
*aCount = mNumCSSStyleSheetURLs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddNamedDataSourceURI(const char* aNamedDataSourceURI)
|
||||
{
|
||||
NS_PRECONDITION(aNamedDataSourceURI != nsnull, "null ptr");
|
||||
if (! aNamedDataSourceURI)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
char** p = new char*[mNumNamedDataSourceURIs + 1];
|
||||
if (! p)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PRInt32 i;
|
||||
for (i = mNumNamedDataSourceURIs - 1; i >= 0; --i)
|
||||
p[i] = mNamedDataSourceURIs[i];
|
||||
|
||||
PRInt32 len = PL_strlen(aNamedDataSourceURI);
|
||||
char* buf = new char[len + 1];
|
||||
if (! buf) {
|
||||
delete p;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
PL_strcpy(buf, aNamedDataSourceURI);
|
||||
p[mNumNamedDataSourceURIs] = buf;
|
||||
|
||||
++mNumNamedDataSourceURIs;
|
||||
mNamedDataSourceURIs = p;
|
||||
|
||||
for (i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
nsIRDFXMLDataSourceObserver* obs = (nsIRDFXMLDataSourceObserver*) mObservers[i];
|
||||
obs->OnNamedDataSourceAdded(this, aNamedDataSourceURI);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount)
|
||||
{
|
||||
*aNamedDataSourceURIs = mNamedDataSourceURIs;
|
||||
*aCount = mNumNamedDataSourceURIs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver)
|
||||
{
|
||||
mObservers.AppendElement(aObserver);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver)
|
||||
{
|
||||
mObservers.RemoveElement(aObserver);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFXMLSource methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXMLDataSourceImpl::Serialize(nsIOutputStream* stream)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIRDFXMLSource* source;
|
||||
if (NS_SUCCEEDED(rv = mInner->QueryInterface(kIRDFXMLSourceIID, (void**) &source))) {
|
||||
rv = source->Serialize(stream);
|
||||
NS_RELEASE(source);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
527
mozilla/rdf/base/src/rdfutil.cpp
Normal file
527
mozilla/rdf/base/src/rdfutil.cpp
Normal file
@@ -0,0 +1,527 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Implementations for a bunch of useful RDF utility routines. Many of
|
||||
these will eventually be exported outside of RDF.DLL via the
|
||||
nsIRDFService interface.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "rdfutil.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// RDF core vocabulary
|
||||
|
||||
#include "rdf.h"
|
||||
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
|
||||
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Alt);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Description);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, ID);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, RDF);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Seq);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, about);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, aboutEach);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, bagID);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, li);
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, resource);
|
||||
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static nsIRDFService* gRDFService = nsnull;
|
||||
|
||||
static nsresult
|
||||
rdf_EnsureRDFService(void)
|
||||
{
|
||||
if (gRDFService)
|
||||
return NS_OK;
|
||||
|
||||
return nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &gRDFService);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRBool
|
||||
rdf_IsOrdinalProperty(const nsIRDFResource* property)
|
||||
{
|
||||
const char* s;
|
||||
if (NS_FAILED(property->GetValue(&s)))
|
||||
return PR_FALSE;
|
||||
|
||||
nsAutoString uri = s;
|
||||
|
||||
if (uri.Find(kRDFNameSpaceURI) != 0)
|
||||
return PR_FALSE;
|
||||
|
||||
nsAutoString tag(uri);
|
||||
tag.Cut(0, sizeof(kRDFNameSpaceURI) - 1);
|
||||
|
||||
if (tag[0] != '_')
|
||||
return PR_FALSE;
|
||||
|
||||
for (PRInt32 i = tag.Length() - 1; i >= 1; --i) {
|
||||
if (tag[i] < '0' || tag[i] > '9')
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
rdf_IsContainer(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* resource)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
nsIRDFResource* RDF_instanceOf = nsnull;
|
||||
nsIRDFResource* RDF_Bag = nsnull;
|
||||
nsIRDFResource* RDF_Seq = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_instanceOf, &RDF_instanceOf)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Bag, &RDF_Bag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = ds->HasAssertion(resource, RDF_instanceOf, RDF_Bag, PR_TRUE, &result)))
|
||||
goto done;
|
||||
|
||||
if (result)
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_Seq, &RDF_Seq)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = ds->HasAssertion(resource, RDF_instanceOf, RDF_Seq, PR_TRUE, &result)))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(RDF_Seq);
|
||||
NS_IF_RELEASE(RDF_Bag);
|
||||
NS_IF_RELEASE(RDF_instanceOf);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// A complete hack that looks at the string value of a node and
|
||||
// guesses if it's a resource
|
||||
static PRBool
|
||||
rdf_IsResource(const nsString& s)
|
||||
{
|
||||
PRInt32 index;
|
||||
|
||||
// A URI needs a colon.
|
||||
index = s.Find(':');
|
||||
if (index < 0)
|
||||
return PR_FALSE;
|
||||
|
||||
// Assume some sane maximum for protocol specs
|
||||
#define MAX_PROTOCOL_SPEC 10
|
||||
if (index > MAX_PROTOCOL_SPEC)
|
||||
return PR_FALSE;
|
||||
|
||||
// It can't have spaces or newlines or tabs
|
||||
if (s.Find(' ') > 0 || s.Find('\n') > 0 || s.Find('\t') > 0)
|
||||
return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// 0. node, node, node
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(subject, "null ptr");
|
||||
NS_ASSERTION(predicate, "null ptr");
|
||||
NS_ASSERTION(object, "null ptr");
|
||||
|
||||
#ifdef DEBUG
|
||||
const char* s;
|
||||
predicate->GetValue(&s);
|
||||
printf(" %s", (strchr(s, '#') ? strchr(s, '#')+1 : s));
|
||||
subject->GetValue(&s);
|
||||
printf("(%s, ", s);
|
||||
|
||||
|
||||
nsIRDFResource* objectResource;
|
||||
nsIRDFLiteral* objectLiteral;
|
||||
|
||||
if (NS_SUCCEEDED(object->QueryInterface(kIRDFResourceIID, (void**) &objectResource))) {
|
||||
objectResource->GetValue(&s);
|
||||
printf(" %s)\n", s);
|
||||
NS_RELEASE(objectResource);
|
||||
}
|
||||
else if (NS_SUCCEEDED(object->QueryInterface(kIRDFLiteralIID, (void**) &objectLiteral))) {
|
||||
const PRUnichar* p;
|
||||
objectLiteral->GetValue(&p);
|
||||
nsAutoString s2(p);
|
||||
char buf[1024];
|
||||
printf(" %s)\n", s2.ToCString(buf, sizeof buf));
|
||||
NS_RELEASE(objectLiteral);
|
||||
}
|
||||
#endif
|
||||
return ds->Assert(subject, predicate, object, PR_TRUE);
|
||||
}
|
||||
|
||||
|
||||
// 1. string, string, string
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
const nsString& subjectURI,
|
||||
const nsString& predicateURI,
|
||||
const nsString& objectURI)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
nsIRDFResource* subject;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(subjectURI, &subject)))
|
||||
return rv;
|
||||
|
||||
rv = rdf_Assert(ds, subject, predicateURI, objectURI);
|
||||
NS_RELEASE(subject);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 2. node, node, string
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
const nsString& objectURI)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(subject, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
nsIRDFNode* object;
|
||||
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
// XXX Make a guess *here* if the object should be a resource or a
|
||||
// literal. If you don't like it, then call ds->Assert() yerself.
|
||||
if (rdf_IsResource(objectURI)) {
|
||||
nsIRDFResource* resource;
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(objectURI, &resource)))
|
||||
return rv;
|
||||
|
||||
object = resource;
|
||||
}
|
||||
else {
|
||||
nsIRDFLiteral* literal;
|
||||
if (NS_FAILED(rv = gRDFService->GetLiteral(objectURI, &literal)))
|
||||
return rv;
|
||||
|
||||
object = literal;
|
||||
}
|
||||
|
||||
rv = rdf_Assert(ds, subject, predicate, object);
|
||||
NS_RELEASE(object);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// 3. node, string, string
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
const nsString& predicateURI,
|
||||
const nsString& objectURI)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(subject, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
nsIRDFResource* predicate;
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(predicateURI, &predicate)))
|
||||
return rv;
|
||||
|
||||
rv = rdf_Assert(ds, subject, predicate, objectURI);
|
||||
NS_RELEASE(predicate);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 4. node, string, node
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
const nsString& predicateURI,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(subject, "null ptr");
|
||||
NS_ASSERTION(object, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
nsIRDFResource* predicate;
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(predicateURI, &predicate)))
|
||||
return rv;
|
||||
|
||||
rv = rdf_Assert(ds, subject, predicate, object);
|
||||
NS_RELEASE(predicate);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 5. string, string, node
|
||||
nsresult
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
const nsString& subjectURI,
|
||||
const nsString& predicateURI,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
nsIRDFResource* subject;
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(subjectURI, &subject)))
|
||||
return rv;
|
||||
|
||||
rv = rdf_Assert(ds, subject, predicateURI, object);
|
||||
NS_RELEASE(subject);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
rdf_CreateAnonymousResource(nsIRDFResource** result)
|
||||
{
|
||||
static PRUint32 gCounter = 0;
|
||||
|
||||
nsAutoString s = "$";
|
||||
s.Append(++gCounter, 10);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
return gRDFService->GetUnicodeResource(s, result);
|
||||
}
|
||||
|
||||
nsresult
|
||||
rdf_MakeBag(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* bag)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(bag, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXX check to see if someone else has already made this into a container.
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, bag, kURIRDF_instanceOf, kURIRDF_Bag)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, bag, kURIRDF_nextVal, "1")))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
rdf_MakeSeq(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* seq)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(seq, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXX check to see if someone else has already made this into a container.
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, seq, kURIRDF_instanceOf, kURIRDF_Seq)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, seq, kURIRDF_nextVal, "1")))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
rdf_MakeAlt(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* alt)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(alt, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXX check to see if someone else has already made this into a container.
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, alt, kURIRDF_instanceOf, kURIRDF_Alt)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, alt, kURIRDF_nextVal, "1")))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
rdf_ContainerGetNextValue(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container,
|
||||
nsIRDFResource** result)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(container, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = rdf_EnsureRDFService()))
|
||||
return rv;
|
||||
|
||||
nsIRDFResource* RDF_nextVal = nsnull;
|
||||
nsIRDFNode* nextValNode = nsnull;
|
||||
nsIRDFLiteral* nextValLiteral = nsnull;
|
||||
const PRUnichar* s;
|
||||
nsAutoString nextValStr;
|
||||
PRInt32 nextVal;
|
||||
PRInt32 err;
|
||||
|
||||
// Get the next value, which hangs off of the bag via the
|
||||
// RDF:nextVal property.
|
||||
if (NS_FAILED(rv = gRDFService->GetResource(kURIRDF_nextVal, &RDF_nextVal)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = ds->GetTarget(container, RDF_nextVal, PR_TRUE, &nextValNode)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nextValNode->QueryInterface(kIRDFLiteralIID, (void**) &nextValLiteral)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = nextValLiteral->GetValue(&s)))
|
||||
goto done;
|
||||
|
||||
nextValStr = s;
|
||||
nextVal = nextValStr.ToInteger(&err);
|
||||
if (NS_FAILED(err))
|
||||
goto done;
|
||||
|
||||
// Generate a URI that we can return.
|
||||
nextValStr = kRDFNameSpaceURI;
|
||||
nextValStr.Append("_");
|
||||
nextValStr.Append(nextVal, 10);
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetUnicodeResource(nextValStr, result)))
|
||||
goto done;
|
||||
|
||||
// Now increment the RDF:nextVal property.
|
||||
if (NS_FAILED(rv = ds->Unassert(container, RDF_nextVal, nextValLiteral)))
|
||||
goto done;
|
||||
|
||||
NS_RELEASE(nextValLiteral);
|
||||
|
||||
++nextVal;
|
||||
nextValStr.Truncate();
|
||||
nextValStr.Append(nextVal, 10);
|
||||
|
||||
if (NS_FAILED(rv = gRDFService->GetLiteral(nextValStr, &nextValLiteral)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, container, RDF_nextVal, nextValLiteral)))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(nextValLiteral);
|
||||
NS_IF_RELEASE(nextValNode);
|
||||
NS_IF_RELEASE(RDF_nextVal);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
rdf_ContainerAddElement(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container,
|
||||
nsIRDFNode* element)
|
||||
{
|
||||
NS_ASSERTION(ds, "null ptr");
|
||||
NS_ASSERTION(container, "null ptr");
|
||||
NS_ASSERTION(element, "null ptr");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsIRDFResource* nextVal;
|
||||
|
||||
if (NS_FAILED(rv = rdf_ContainerGetNextValue(ds, container, &nextVal)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = rdf_Assert(ds, container, nextVal, element)))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
169
mozilla/rdf/base/src/rdfutil.h
Normal file
169
mozilla/rdf/base/src/rdfutil.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
A bunch of useful RDF utility routines. Many of these will
|
||||
eventually be exported outside of RDF.DLL via the nsIRDFService
|
||||
interface.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef rdfutil_h__
|
||||
#define rdfutil_h__
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsIRDFCursor;
|
||||
class nsIRDFDataBase;
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFNode;
|
||||
class nsString;
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if the URI is an RDF ordinal property; e.g., rdf:_1,
|
||||
* rdf:_2, etc.
|
||||
*/
|
||||
PR_EXTERN(PRBool)
|
||||
rdf_IsOrdinalProperty(const nsIRDFResource* property);
|
||||
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if the resource is a container resource; e.g., an
|
||||
* rdf:Bag.
|
||||
*/
|
||||
PR_EXTERN(PRBool)
|
||||
rdf_IsContainer(nsIRDFDataSource* db,
|
||||
nsIRDFResource* resource);
|
||||
|
||||
|
||||
/**
|
||||
* Various utilities routines for making assertions in a data source
|
||||
*/
|
||||
|
||||
// 0. node, node, node
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object);
|
||||
|
||||
// 1. string, string, string
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
const nsString& subjectURI,
|
||||
const nsString& predicateURI,
|
||||
const nsString& objectURI);
|
||||
|
||||
// 2. node, node, string
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
const nsString& objectURI);
|
||||
|
||||
// 3. node, string, string
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
const nsString& predicateURI,
|
||||
const nsString& objectURI);
|
||||
|
||||
// 4. node, string, node
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* subject,
|
||||
const nsString& predicateURI,
|
||||
nsIRDFNode* object);
|
||||
|
||||
// 5. string, string, node
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_Assert(nsIRDFDataSource* ds,
|
||||
const nsString& subjectURI,
|
||||
const nsString& predicateURI,
|
||||
nsIRDFNode* object);
|
||||
|
||||
/**
|
||||
* Construct a new, "anonymous" node; that is, a node with an internal
|
||||
* resource URI.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_CreateAnonymousResource(nsIRDFResource** result);
|
||||
|
||||
|
||||
/**
|
||||
* Create a bag resource.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_MakeBag(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* resource);
|
||||
|
||||
/**
|
||||
* Create a sequence resource.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_MakeSeq(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* resource);
|
||||
|
||||
/**
|
||||
* Create an alternation resource.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_MakeAlt(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* resource);
|
||||
|
||||
|
||||
/**
|
||||
* Add an element to the container.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
rdf_ContainerAddElement(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container,
|
||||
nsIRDFNode* element);
|
||||
|
||||
/**
|
||||
* Create a cursor on a container that enumerates its contents in
|
||||
* order
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
NS_NewContainerCursor(nsIRDFDataSource* ds,
|
||||
nsIRDFResource* container,
|
||||
nsIRDFAssertionCursor** cursor);
|
||||
|
||||
|
||||
/**
|
||||
* Create an empty nsIRDFCursor. This will *never* fail, and will *always*
|
||||
* return the same object.
|
||||
*/
|
||||
PR_EXTERN(nsresult)
|
||||
NS_NewEmptyRDFAssertionCursor(nsIRDFAssertionCursor** result);
|
||||
|
||||
PR_EXTERN(nsresult)
|
||||
NS_NewEmptyRDFArcsInCursor(nsIRDFArcsInCursor** result);
|
||||
|
||||
PR_EXTERN(nsresult)
|
||||
NS_NewEmptyRDFArcsOutCursor(nsIRDFArcsOutCursor** result);
|
||||
|
||||
|
||||
// XXX need to move nsEmptyCursor stuff here.
|
||||
|
||||
#endif // rdfutil_h__
|
||||
|
||||
|
||||
1
mozilla/rdf/build/MANIFEST
Normal file
1
mozilla/rdf/build/MANIFEST
Normal file
@@ -0,0 +1 @@
|
||||
nsRDFCID.h
|
||||
68
mozilla/rdf/build/Makefile.in
Normal file
68
mozilla/rdf/build/Makefile.in
Normal file
@@ -0,0 +1,68 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBRARY_NAME = rdf
|
||||
|
||||
CPPSRCS = \
|
||||
nsRDFFactory.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsRDFCID.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
REQUIRES = dom js netlib rdf raptor xpcom
|
||||
|
||||
# XXX Note dependencies on implementation headers for factory functions
|
||||
|
||||
INCLUDES += -I$(srcdir)/../base/src \
|
||||
-I$(srcdir)/../content/src \
|
||||
-I$(srcdir)/../datasource/src \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
-L$(DIST)/bin \
|
||||
-L$(DIST)/lib \
|
||||
-lrdfbase_s \
|
||||
-lrdfcontent_s \
|
||||
-lrdfdatasource_s \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
install:: $(TARGETS)
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/inbox $(DIST)/bin/res/rdf/Mail/joe@meer.net
|
||||
$(INSTALL) $(srcdir)/../resources/LocalStore.rdf $(DIST)/bin/res/rdf
|
||||
$(INSTALL) $(srcdir)/../resources/LocalStore.css $(DIST)/bin/res/rdf
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/work $(DIST)/bin/res/rdf/Mail/joe@meer.net
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/other $(DIST)/bin/res/rdf/Mail/joe@meer.net
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/inbox $(DIST)/bin/res/rdf/Mail/jane@aol.com
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/hiking $(DIST)/bin/res/rdf/Mail/jane@aol.com
|
||||
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/trash $(DIST)/bin/res/rdf/Mail/jane@aol.com
|
||||
76
mozilla/rdf/build/makefile.win
Normal file
76
mozilla/rdf/build/makefile.win
Normal file
@@ -0,0 +1,76 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..
|
||||
MODULE=rdf
|
||||
|
||||
MAKE_OBJ_TYPE=DLL
|
||||
DLLNAME=rdf
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
|
||||
EXPORTS=\
|
||||
nsRDFCID.h \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS=\
|
||||
.\$(OBJDIR)\nsRDFFactory.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS=\
|
||||
$(DIST)\lib\rdfbase_s.lib \
|
||||
$(DIST)\lib\rdfcontent_s.lib \
|
||||
$(DIST)\lib\rdfdatasource_s.lib \
|
||||
$(DIST)\lib\xpcom32.lib \
|
||||
$(DIST)\lib\raptorbase.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\netlib.lib \
|
||||
$(DIST)\lib\libplc21.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
MISCDEP=$(LLIBS)
|
||||
|
||||
# XXX Note dependencies on implementation dirs for factory methods.
|
||||
|
||||
LINCS= -I$(PUBLIC)\rdf \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
-I$(PUBLIC)\netlib \
|
||||
-I$(PUBLIC)\raptor \
|
||||
-I$(PUBLIC)\js \
|
||||
-I$(PUBLIC)\dom \
|
||||
-I$(DEPTH)\rdf\base\src \
|
||||
-I$(DEPTH)\rdf\content\src \
|
||||
-I$(DEPTH)\rdf\datasource\src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\inbox $(DIST)\bin\res\rdf\Mail\joe@meer.net
|
||||
$(MAKE_INSTALL) ..\resources\LocalStore.rdf $(DIST)\bin\res\rdf
|
||||
$(MAKE_INSTALL) ..\resources\bookmarks.html $(DIST)\bin\res\rdf
|
||||
$(MAKE_INSTALL) ..\resources\LocalStore.css $(DIST)\bin\res\rdf
|
||||
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\work $(DIST)\bin\res\rdf\Mail\joe@meer.net
|
||||
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\other $(DIST)\bin\res\rdf\Mail\joe@meer.net
|
||||
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\inbox $(DIST)\bin\res\rdf\Mail\jane@aol.com
|
||||
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\hiking $(DIST)\bin\res\rdf\Mail\jane@aol.com
|
||||
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\trash $(DIST)\bin\res\rdf\Mail\jane@aol.com
|
||||
|
||||
|
||||
|
||||
|
||||
71
mozilla/rdf/build/nsRDFCID.h
Normal file
71
mozilla/rdf/build/nsRDFCID.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
XPCOM Class IDs for RDF objects that can be constructed via the RDF
|
||||
factory.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsRDFCID_h__
|
||||
#define nsRDFCID_h__
|
||||
|
||||
// {0F78DA56-8321-11d2-8EAC-00805F29F370}
|
||||
#define NS_RDFNODE_CID \
|
||||
{ 0xf78da56, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {BFD05264-834C-11d2-8EAC-00805F29F370}
|
||||
#define NS_RDFSERVICE_CID \
|
||||
{ 0xbfd05264, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {BFD0526D-834C-11d2-8EAC-00805F29F370}
|
||||
#define NS_RDFINMEMORYDATASOURCE_CID \
|
||||
{ 0xbfd0526d, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {E638D760-8687-11d2-B530-000000000000}
|
||||
#define NS_RDFBOOKMARKDATASOURCE_CID \
|
||||
{ 0xe638d760, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
|
||||
|
||||
// {E638D761-8687-11d2-B530-000000000000}
|
||||
#define NS_RDFCOMPOSITEDATASOURCE_CID \
|
||||
{ 0xe638d761, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
|
||||
|
||||
// {541AFCB2-A9A3-11d2-8EC5-00805F29F370}
|
||||
#define NS_RDFDOCUMENT_CID \
|
||||
{ 0x541afcb2, 0xa9a3, 0x11d2, { 0x8e, 0xc5, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {954F0813-81DC-11d2-B52A-000000000000}
|
||||
#define NS_RDFHTMLBUILDER_CID \
|
||||
{ 0x954f0813, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
|
||||
|
||||
// {3D262D00-8B5A-11d2-8EB0-00805F29F370}
|
||||
#define NS_RDFTREEBUILDER_CID \
|
||||
{ 0x3d262d00, 0x8b5a, 0x11d2, { 0x8e, 0xb0, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {7BAF62E0-8E61-11d2-8EB1-00805F29F370}
|
||||
#define NS_RDFXMLDATASOURCE_CID \
|
||||
{ 0x7baf62e0, 0x8e61, 0x11d2, { 0x8e, 0xb1, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
// {0958B101-9ADA-11d2-8EBC-00805F29F370}
|
||||
#define NS_RDFCONTENTSINK_CID \
|
||||
{ 0x958b101, 0x9ada, 0x11d2, { 0x8e, 0xbc, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
|
||||
|
||||
#endif // nsRDFCID_h__
|
||||
204
mozilla/rdf/build/nsRDFFactory.cpp
Normal file
204
mozilla/rdf/build/nsRDFFactory.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The RDF factory implementation.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFContentSink.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFXMLDataSource.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsRDFBaseDataSources.h"
|
||||
#include "nsRDFBuiltInDataSources.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
|
||||
static NS_DEFINE_CID(kRDFBookmarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFCompositeDataSourceCID, NS_RDFCOMPOSITEDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFDocumentCID, NS_RDFDOCUMENT_CID);
|
||||
static NS_DEFINE_CID(kRDFHTMLBuilderCID, NS_RDFHTMLBUILDER_CID);
|
||||
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
|
||||
static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFTreeBuilderCID, NS_RDFTREEBUILDER_CID);
|
||||
|
||||
class RDFFactoryImpl : public nsIFactory
|
||||
{
|
||||
public:
|
||||
RDFFactoryImpl(const nsCID &aClass);
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFactory methods
|
||||
NS_IMETHOD CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult);
|
||||
|
||||
NS_IMETHOD LockFactory(PRBool aLock);
|
||||
|
||||
protected:
|
||||
virtual ~RDFFactoryImpl();
|
||||
|
||||
private:
|
||||
nsCID mClassID;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RDFFactoryImpl::RDFFactoryImpl(const nsCID &aClass)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mClassID = aClass;
|
||||
}
|
||||
|
||||
RDFFactoryImpl::~RDFFactoryImpl()
|
||||
{
|
||||
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFFactoryImpl::QueryInterface(const nsIID &aIID,
|
||||
void **aResult)
|
||||
{
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Always NULL result, in case of failure
|
||||
*aResult = nsnull;
|
||||
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aResult = NS_STATIC_CAST(nsISupports*, this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
} else if (aIID.Equals(kIFactoryIID)) {
|
||||
*aResult = NS_STATIC_CAST(nsIFactory*, this);
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(RDFFactoryImpl);
|
||||
NS_IMPL_RELEASE(RDFFactoryImpl);
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFFactoryImpl::CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult)
|
||||
{
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
*aResult = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
PRBool wasRefCounted = PR_TRUE;
|
||||
nsISupports *inst = nsnull;
|
||||
if (mClassID.Equals(kRDFServiceCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFService((nsIRDFService**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFInMemoryDataSourceCID)) {
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFInMemoryDataSource((nsIRDFDataSource**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFXMLDataSourceCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFXMLDataSource((nsIRDFXMLDataSource**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFBookmarkDataSourceCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFBookmarkDataSource((nsIRDFDataSource**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFCompositeDataSourceCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFCompositeDataSource((nsIRDFCompositeDataSource**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFDocumentCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFDocument((nsIRDFDocument**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFHTMLBuilderCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFHTMLBuilder((nsIRDFContentModelBuilder**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFTreeBuilderCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFTreeBuilder((nsIRDFContentModelBuilder**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else if (mClassID.Equals(kRDFContentSinkCID)) {
|
||||
if (NS_FAILED(rv = NS_NewRDFContentSink((nsIRDFContentSink**) &inst)))
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
if (! inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (NS_FAILED(rv = inst->QueryInterface(aIID, aResult)))
|
||||
// We didn't get the right interface, so clean up
|
||||
delete inst;
|
||||
|
||||
if (wasRefCounted)
|
||||
NS_IF_RELEASE(inst);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult RDFFactoryImpl::LockFactory(PRBool aLock)
|
||||
{
|
||||
// Not implemented in simplest case.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// return the proper factory to the caller
|
||||
extern "C" PR_IMPLEMENT(nsresult)
|
||||
NSGetFactory(const nsCID &aClass, nsIFactory **aFactory)
|
||||
{
|
||||
if (! aFactory)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aFactory = new RDFFactoryImpl(aClass);
|
||||
if (aFactory == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory);
|
||||
}
|
||||
|
||||
29
mozilla/rdf/content/Makefile.in
Normal file
29
mozilla/rdf/content/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
27
mozilla/rdf/content/makefile.win
Normal file
27
mozilla/rdf/content/makefile.win
Normal file
@@ -0,0 +1,27 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
DIRS=\
|
||||
public \
|
||||
src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
3
mozilla/rdf/content/public/MANIFEST
Normal file
3
mozilla/rdf/content/public/MANIFEST
Normal file
@@ -0,0 +1,3 @@
|
||||
nsIRDFContent.h
|
||||
nsIRDFContentModelBuilder.h
|
||||
nsIRDFDocument.h
|
||||
37
mozilla/rdf/content/public/Makefile.in
Normal file
37
mozilla/rdf/content/public/Makefile.in
Normal file
@@ -0,0 +1,37 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
EXPORTS = \
|
||||
nsIRDFContent.h \
|
||||
nsIRDFContentModelBuilder.h \
|
||||
nsIRDFDocument.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
30
mozilla/rdf/content/public/makefile.win
Normal file
30
mozilla/rdf/content/public/makefile.win
Normal file
@@ -0,0 +1,30 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
MODULE=rdf
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
EXPORTS = \
|
||||
nsIRDFContent.h \
|
||||
nsIRDFContentModelBuilder.h \
|
||||
nsIRDFDocument.h \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
60
mozilla/rdf/content/public/nsIRDFContent.h
Normal file
60
mozilla/rdf/content/public/nsIRDFContent.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An interface for RDF content model elements.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFContent_h___
|
||||
#define nsIRDFContent_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIXMLContent.h"
|
||||
|
||||
class nsIRDFResource;
|
||||
|
||||
// {954F0810-81DC-11d2-B52A-000000000000}
|
||||
#define NS_IRDFCONTENT_IID \
|
||||
{ 0x954f0810, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
|
||||
|
||||
/**
|
||||
* RDF content extensions to nsIContent
|
||||
*/
|
||||
class nsIRDFContent : public nsIContent {
|
||||
public:
|
||||
NS_IMETHOD GetResource(nsIRDFResource*& aResource) const = 0;
|
||||
NS_IMETHOD ChildrenHaveBeenGenerated(PRBool& aResult) const = 0;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewRDFResourceElement(nsIRDFContent** aResult,
|
||||
nsIRDFResource* aResource,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
PRBool aChildrenMustBeGenerated);
|
||||
|
||||
nsresult
|
||||
NS_NewRDFGenericElement(nsIContent** aResult,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag);
|
||||
|
||||
|
||||
#endif // nsIRDFContent_h___
|
||||
79
mozilla/rdf/content/public/nsIRDFContentModelBuilder.h
Normal file
79
mozilla/rdf/content/public/nsIRDFContentModelBuilder.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A content model builder interface. An object that implements this
|
||||
interface is associated with an nsIRDFDocument object to construct
|
||||
an NGLayout content model.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFContentModelBuilder_h__
|
||||
#define nsIRDFContentModelBuilder_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIRDFContent;
|
||||
class nsIRDFDocument;
|
||||
class nsIRDFNode;
|
||||
class nsIRDFResource;
|
||||
|
||||
// {541AFCB0-A9A3-11d2-8EC5-00805F29F370}
|
||||
#define NS_IRDFCONTENTMODELBUILDER_IID \
|
||||
{ 0x541afcb0, 0xa9a3, 0x11d2, { 0x8e, 0xc5, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
|
||||
|
||||
class nsIRDFContentModelBuilder : public nsISupports
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Point the content model builder to the document. The content model
|
||||
* builder must not reference count the document.
|
||||
*/
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument) = 0;
|
||||
|
||||
/**
|
||||
* Called to instruct the content model builder to construct the root
|
||||
* document element. The content model builder should construct an
|
||||
* nsIContent object and set the document's content root to that object
|
||||
* via the nsIDocument::SetDocumentRoot() method.
|
||||
*/
|
||||
NS_IMETHOD CreateRoot(nsIRDFResource* aResource) = 0;
|
||||
|
||||
/**
|
||||
* Called when a new assertion is made to the RDF graph that affects an
|
||||
* element in the content model. The content model builder should update
|
||||
* the document's content model as appropriate.
|
||||
*/
|
||||
NS_IMETHOD OnAssert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue) = 0;
|
||||
|
||||
/**
|
||||
* Called when an assertion is removed from the RDF graph that affects
|
||||
* an element in the content model. The content model builder should
|
||||
* update the document's content model as appropriate.
|
||||
*/
|
||||
NS_IMETHOD OnUnassert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue) = 0;
|
||||
};
|
||||
|
||||
|
||||
extern nsresult NS_NewRDFTreeBuilder(nsIRDFContentModelBuilder** aResult);
|
||||
extern nsresult NS_NewRDFHTMLBuilder(nsIRDFContentModelBuilder** aResult);
|
||||
|
||||
|
||||
#endif // nsIRDFContentModelBuilder_h__
|
||||
108
mozilla/rdf/content/public/nsIRDFDocument.h
Normal file
108
mozilla/rdf/content/public/nsIRDFDocument.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An RDF-specific extension to nsIXMLDocument. Includes methods for
|
||||
setting the root resource of the document content model, a factory
|
||||
method for constructing the children of a node, etc.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFDocument_h___
|
||||
#define nsIRDFDocument_h___
|
||||
|
||||
class nsIContent; // XXX nsIXMLDocument.h is bad and doesn't declare this class...
|
||||
|
||||
#include "nsIXMLDocument.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIRDFCompositeDataSource;
|
||||
class nsIRDFContent;
|
||||
class nsIRDFContentModelBuilder;
|
||||
class nsISupportsArray;
|
||||
class nsIRDFResource;
|
||||
|
||||
// {954F0811-81DC-11d2-B52A-000000000000}
|
||||
#define NS_IRDFDOCUMENT_IID \
|
||||
{ 0x954f0811, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
|
||||
|
||||
/**
|
||||
* RDF document extensions to nsIDocument
|
||||
*/
|
||||
class nsIRDFDocument : public nsIXMLDocument
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initialize the document object. This will force the document to create
|
||||
* its internal RDF database.
|
||||
*/
|
||||
NS_IMETHOD Init(nsIRDFContentModelBuilder* aBuilder) = 0;
|
||||
|
||||
/**
|
||||
* Set the document's "root" resource.
|
||||
*/
|
||||
NS_IMETHOD SetRootResource(nsIRDFResource* aResource) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the document's RDF data base.
|
||||
*/
|
||||
NS_IMETHOD GetDataBase(nsIRDFCompositeDataSource*& rDataBase) = 0;
|
||||
|
||||
/**
|
||||
* Given an nsIRDFContent element in the document, create its
|
||||
* "content children," that is, a set of nsIRDFContent elements that
|
||||
* should appear as the node's children in the content model.
|
||||
*/
|
||||
NS_IMETHOD CreateChildren(nsIRDFContent* element) = 0;
|
||||
|
||||
// XXX the following two methods should probably accept strings as
|
||||
// parameters so you can mess with them via JS. Also, should they
|
||||
// take a "notify" parameter that would control whether any viewers
|
||||
// of the content model should be informed that the content model is
|
||||
// invalid?
|
||||
|
||||
/**
|
||||
* Add a property to the set of "tree properties" that the document
|
||||
* should use when constructing the content model from the RDF
|
||||
* graph.
|
||||
*/
|
||||
NS_IMETHOD AddTreeProperty(nsIRDFResource* resource) = 0;
|
||||
|
||||
/**
|
||||
* Remove a property from the set of "tree properties" that the
|
||||
* document should use when constructing the content model from the
|
||||
* RDF graph.
|
||||
*/
|
||||
NS_IMETHOD RemoveTreeProperty(nsIRDFResource* resource) = 0;
|
||||
|
||||
/**
|
||||
* Determine whether the specified property is a "tree" property.
|
||||
*/
|
||||
NS_IMETHOD IsTreeProperty(nsIRDFResource* aProperty, PRBool* aResult) const = 0;
|
||||
|
||||
NS_IMETHOD MapResource(nsIRDFResource* aResource, nsIRDFContent* aContent) = 0;
|
||||
NS_IMETHOD UnMapResource(nsIRDFResource* aResource, nsIRDFContent* aContent) = 0;
|
||||
NS_IMETHOD SplitProperty(nsIRDFResource* aResource, PRInt32* aNameSpaceID, nsIAtom** aTag) = 0;
|
||||
};
|
||||
|
||||
// factory functions
|
||||
nsresult NS_NewRDFDocument(nsIRDFDocument** result);
|
||||
|
||||
#endif // nsIRDFDocument_h___
|
||||
58
mozilla/rdf/content/src/Makefile.in
Normal file
58
mozilla/rdf/content/src/Makefile.in
Normal file
@@ -0,0 +1,58 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBRARY_NAME = rdfcontent_s
|
||||
|
||||
CPPSRCS = \
|
||||
nsRDFContentUtils.cpp \
|
||||
nsRDFDOMNodeList.cpp \
|
||||
nsRDFDocument.cpp \
|
||||
nsRDFGenericElement.cpp \
|
||||
nsRDFHTMLBuilder.cpp \
|
||||
nsRDFResourceElement.cpp \
|
||||
nsRDFTreeBuilder.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
REQUIRES = dom js netlib rdf raptor xpcom
|
||||
|
||||
# XXX This is a dependency on rdfutil.h: it'll go away once that becomes
|
||||
# a first-class XPCOM interface.
|
||||
INCLUDES += -I$(srcdir)/../../base/src
|
||||
|
||||
MKSHLIB :=
|
||||
|
||||
# we don't want the shared lib
|
||||
NO_SHARED_LIB=1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
49
mozilla/rdf/content/src/makefile.win
Normal file
49
mozilla/rdf/content/src/makefile.win
Normal file
@@ -0,0 +1,49 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=rdf
|
||||
LIBRARY_NAME=rdfcontent_s
|
||||
|
||||
CPP_OBJS=\
|
||||
.\$(OBJDIR)\nsRDFContentUtils.obj \
|
||||
.\$(OBJDIR)\nsRDFDOMNodeList.obj \
|
||||
.\$(OBJDIR)\nsRDFDocument.obj \
|
||||
.\$(OBJDIR)\nsRDFGenericElement.obj \
|
||||
.\$(OBJDIR)\nsRDFHTMLBuilder.obj \
|
||||
.\$(OBJDIR)\nsRDFResourceElement.obj \
|
||||
.\$(OBJDIR)\nsRDFTreeBuilder.obj \
|
||||
$(NULL)
|
||||
|
||||
LINCS= -I$(PUBLIC)\rdf \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
-I$(PUBLIC)\netlib \
|
||||
-I$(PUBLIC)\raptor \
|
||||
-I$(PUBLIC)\js \
|
||||
-I$(PUBLIC)\dom \
|
||||
-I$(DEPTH)\rdf\base\src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
libs:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
|
||||
53
mozilla/rdf/content/src/nsGenericAttribute.h
Normal file
53
mozilla/rdf/content/src/nsGenericAttribute.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
A helper class used to implement attributes.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsGenericAttribute_h__
|
||||
#define nsGenericAttribute_h__
|
||||
|
||||
class nsGenericAttribute
|
||||
{
|
||||
public:
|
||||
nsGenericAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue)
|
||||
: mNameSpaceID(aNameSpaceID),
|
||||
mName(aName),
|
||||
mValue(aValue)
|
||||
{
|
||||
NS_IF_ADDREF(mName);
|
||||
}
|
||||
|
||||
~nsGenericAttribute(void)
|
||||
{
|
||||
NS_IF_RELEASE(mName);
|
||||
}
|
||||
|
||||
PRInt32 mNameSpaceID;
|
||||
nsIAtom* mName;
|
||||
nsString mValue;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsGenericAttribute_h__
|
||||
|
||||
87
mozilla/rdf/content/src/nsRDFContentUtils.cpp
Normal file
87
mozilla/rdf/content/src/nsRDFContentUtils.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); // XXX grr...
|
||||
static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID);
|
||||
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
rdf_AttachTextNode(nsIContent* parent, nsIRDFNode* value)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoString s;
|
||||
nsIContent* node = nsnull;
|
||||
nsITextContent* text = nsnull;
|
||||
nsIRDFResource* resource = nsnull;
|
||||
nsIRDFLiteral* literal = nsnull;
|
||||
|
||||
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
|
||||
const char* p;
|
||||
if (NS_FAILED(rv = resource->GetValue(&p)))
|
||||
goto error;
|
||||
|
||||
s = p;
|
||||
}
|
||||
else if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
|
||||
const PRUnichar* p;
|
||||
if (NS_FAILED(rv = literal->GetValue(&p)))
|
||||
goto error;
|
||||
|
||||
s = p;
|
||||
}
|
||||
else {
|
||||
PR_ASSERT(0);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kTextNodeCID,
|
||||
nsnull,
|
||||
kIContentIID,
|
||||
(void**) &node)))
|
||||
goto error;
|
||||
|
||||
if (NS_FAILED(rv = node->QueryInterface(kITextContentIID, (void**) &text)))
|
||||
goto error;
|
||||
|
||||
if (NS_FAILED(rv = text->SetText(s.GetUnicode(), s.Length(), PR_FALSE)))
|
||||
goto error;
|
||||
|
||||
// hook it up to the child
|
||||
if (NS_FAILED(rv = parent->AppendChildTo(NS_STATIC_CAST(nsIContent*, node), PR_TRUE)))
|
||||
goto error;
|
||||
|
||||
error:
|
||||
NS_IF_RELEASE(node);
|
||||
NS_IF_RELEASE(text);
|
||||
return rv;
|
||||
}
|
||||
|
||||
49
mozilla/rdf/content/src/nsRDFContentUtils.h
Normal file
49
mozilla/rdf/content/src/nsRDFContentUtils.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Utility routines used throughout the content model library.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsRDFContentUtils_h__
|
||||
#define nsRDFContentUtils_h__
|
||||
|
||||
#include "nsError.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIDOMNodeList;
|
||||
class nsIRDFNode;
|
||||
class nsString;
|
||||
|
||||
nsresult
|
||||
rdf_GetQuotedAttributeValue(const nsString& aSource,
|
||||
const nsString& aAttribute,
|
||||
nsString& aValue);
|
||||
|
||||
nsresult
|
||||
rdf_AttachTextNode(nsIContent* parent, nsIRDFNode* value);
|
||||
|
||||
// In nsRDFDOMNodeList.cpp
|
||||
extern nsresult
|
||||
NS_NewRDFDOMNodeList(nsIDOMNodeList** aChildNodes, nsIContent* aElement);
|
||||
|
||||
#endif // nsRDFContentUtils_h__
|
||||
|
||||
107
mozilla/rdf/content/src/nsRDFDOMNodeList.cpp
Normal file
107
mozilla/rdf/content/src/nsRDFDOMNodeList.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Helper class to implement the nsIDOMNodeList interface.
|
||||
|
||||
XXX It's probably wrong in some sense, as it uses the "naked"
|
||||
content interface to look for kids. (I assume in general this is
|
||||
bad because there may be pseudo-elements created for presentation
|
||||
that aren't visible to the DOM.)
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
|
||||
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
||||
static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID);
|
||||
|
||||
|
||||
class RDFDOMNodeListImpl : public nsIDOMNodeList {
|
||||
private:
|
||||
nsIContent* mElement;
|
||||
|
||||
public:
|
||||
RDFDOMNodeListImpl(nsIContent* element) : mElement(element) {
|
||||
NS_IF_ADDREF(mElement);
|
||||
}
|
||||
|
||||
virtual ~RDFDOMNodeListImpl(void) {
|
||||
NS_IF_RELEASE(mElement);
|
||||
}
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_IDOMNODELIST
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFDOMNodeListImpl, kIDOMNodeListIID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFDOMNodeListImpl::GetLength(PRUint32* aLength)
|
||||
{
|
||||
PRInt32 count;
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = mElement->ChildCount(count)))
|
||||
return rv;
|
||||
*aLength = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFDOMNodeListImpl::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
||||
{
|
||||
// XXX naive. probably breaks when there are pseudo elements or something.
|
||||
nsresult rv;
|
||||
nsIContent* contentChild;
|
||||
if (NS_FAILED(rv = mElement->ChildAt(aIndex, contentChild)))
|
||||
return rv;
|
||||
|
||||
rv = contentChild->QueryInterface(kIDOMNodeIID, (void**) aReturn);
|
||||
NS_RELEASE(contentChild);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFDOMNodeList(nsIDOMNodeList** aResult, nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
RDFDOMNodeListImpl* list = new RDFDOMNodeListImpl(aElement);
|
||||
if (! list)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(list);
|
||||
*aResult = list;
|
||||
return NS_OK;
|
||||
}
|
||||
2002
mozilla/rdf/content/src/nsRDFDocument.cpp
Normal file
2002
mozilla/rdf/content/src/nsRDFDocument.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1130
mozilla/rdf/content/src/nsRDFGenericElement.cpp
Normal file
1130
mozilla/rdf/content/src/nsRDFGenericElement.cpp
Normal file
File diff suppressed because it is too large
Load Diff
320
mozilla/rdf/content/src/nsRDFHTMLBuilder.cpp
Normal file
320
mozilla/rdf/content/src/nsRDFHTMLBuilder.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An nsIRDFDocument implementation that builds an HTML-like model,
|
||||
complete with text nodes. The model can be displayed in a vanilla
|
||||
HTML content viewer by applying CSS2 styles to the text.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContent.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "rdfutil.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFContentModelBuilderIID, NS_IRDFCONTENTMODELBUILDER_IID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RDFHTMLBuilderImpl : public nsIRDFContentModelBuilder
|
||||
{
|
||||
private:
|
||||
nsIRDFDocument* mDocument;
|
||||
nsIRDFCompositeDataSource* mDB;
|
||||
|
||||
public:
|
||||
RDFHTMLBuilderImpl();
|
||||
virtual ~RDFHTMLBuilderImpl();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD CreateRoot(nsIRDFResource* aResource);
|
||||
NS_IMETHOD OnAssert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue);
|
||||
NS_IMETHOD OnUnassert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue);
|
||||
|
||||
// Implementation methods
|
||||
nsresult AddTreeChild(nsIRDFContent* aParent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value);
|
||||
|
||||
nsresult AddLeafChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFLiteral* value);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static nsIAtom* kIdAtom;
|
||||
|
||||
RDFHTMLBuilderImpl::RDFHTMLBuilderImpl(void)
|
||||
: mDocument(nsnull),
|
||||
mDB(nsnull)
|
||||
{
|
||||
if (nsnull == kIdAtom) {
|
||||
kIdAtom = NS_NewAtom("ID");
|
||||
}
|
||||
else {
|
||||
NS_ADDREF(kIdAtom);
|
||||
}
|
||||
}
|
||||
|
||||
RDFHTMLBuilderImpl::~RDFHTMLBuilderImpl(void)
|
||||
{
|
||||
nsrefcnt refcnt;
|
||||
NS_RELEASE2(kIdAtom, refcnt);
|
||||
|
||||
NS_IF_RELEASE(mDB);
|
||||
// mDocument is _not_ refcounted
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFHTMLBuilderImpl, kIRDFContentModelBuilderIID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
RDFHTMLBuilderImpl::AddTreeChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value)
|
||||
{
|
||||
// If it's a tree property, then create a child element whose
|
||||
// value is the value of the property. We'll also attach an "ID="
|
||||
// attribute to the new child; e.g.,
|
||||
//
|
||||
// <parent>
|
||||
// <property id="value">
|
||||
// <!-- recursively generated -->
|
||||
// </property>
|
||||
// ...
|
||||
// </parent>
|
||||
|
||||
nsresult rv;
|
||||
PRInt32 nameSpaceID;
|
||||
nsIAtom* tag = nsnull;
|
||||
nsIRDFContent* child = nsnull;
|
||||
const char* p;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, &tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&child, value, nameSpaceID, tag, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = value->GetValue(&p)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = child->SetAttribute(kNameSpaceID_HTML, kIdAtom, p, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
rv = parent->AppendChildTo(child, PR_TRUE);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(child);
|
||||
NS_IF_RELEASE(tag);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFHTMLBuilderImpl::AddLeafChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFLiteral* value)
|
||||
{
|
||||
// Otherwise, it's not a tree property. So we'll just create a
|
||||
// new element for the property, and a simple text node for
|
||||
// its value; e.g.,
|
||||
//
|
||||
// <parent>
|
||||
// <property>value</property>
|
||||
// ...
|
||||
// </parent>
|
||||
|
||||
nsresult rv;
|
||||
PRInt32 nameSpaceID;
|
||||
nsIAtom* tag = nsnull;
|
||||
nsIRDFContent* child = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, &tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&child, property, nameSpaceID, tag, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = parent->AppendChildTo(child, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
rv = rdf_AttachTextNode(child, value);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(tag);
|
||||
NS_IF_RELEASE(child);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFHTMLBuilderImpl::SetDocument(nsIRDFDocument* aDocument)
|
||||
{
|
||||
NS_PRECONDITION(aDocument != nsnull, "null ptr");
|
||||
if (! aDocument)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mDocument = aDocument; // not refcounted
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = mDocument->GetDataBase(mDB)))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFHTMLBuilderImpl::CreateRoot(nsIRDFResource* aResource)
|
||||
{
|
||||
NS_PRECONDITION(mDocument != nsnull, "not initialized");
|
||||
if (! mDocument)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
nsIAtom* tag = nsnull;
|
||||
nsIDocument* doc = nsnull;
|
||||
nsIContent* root = nsnull;
|
||||
nsIRDFContent* body = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->QueryInterface(kIDocumentIID, (void**) &doc)))
|
||||
goto done;
|
||||
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
if ((tag = NS_NewAtom("DOCUMENT")) == nsnull)
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFGenericElement(&root, kNameSpaceID_None, tag)))
|
||||
goto done;
|
||||
|
||||
doc->SetRootContent(NS_STATIC_CAST(nsIContent*, root));
|
||||
|
||||
NS_RELEASE(tag);
|
||||
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
if ((tag = NS_NewAtom("BODY")) == nsnull)
|
||||
goto done;
|
||||
|
||||
// PR_TRUE indicates that children should be recursively generated on demand
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&body, aResource, kNameSpaceID_None, tag, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = root->AppendChildTo(body, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(body);
|
||||
NS_IF_RELEASE(root);
|
||||
NS_IF_RELEASE(tag);
|
||||
NS_IF_RELEASE(doc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFHTMLBuilderImpl::OnAssert(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* value)
|
||||
{
|
||||
NS_PRECONDITION(mDocument != nsnull, "not initialized");
|
||||
if (! mDocument)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsIRDFResource* valueResource;
|
||||
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, (void**) &valueResource))) {
|
||||
// If it's a tree property or an RDF container, then add it as
|
||||
// a tree child and return.
|
||||
PRBool isTreeProperty;
|
||||
if ((NS_SUCCEEDED(rv = mDocument->IsTreeProperty(property, &isTreeProperty)) && isTreeProperty) ||
|
||||
(rdf_IsContainer(mDB, valueResource))) {
|
||||
rv = AddTreeChild(parent, property, valueResource);
|
||||
NS_RELEASE(valueResource);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Otherwise, fall through and add try to add it as a property
|
||||
NS_RELEASE(valueResource);
|
||||
}
|
||||
|
||||
nsIRDFLiteral* valueLiteral;
|
||||
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFLiteralIID, (void**) &valueLiteral))) {
|
||||
rv = AddLeafChild(parent, property, valueLiteral);
|
||||
NS_RELEASE(valueLiteral);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFHTMLBuilderImpl::OnUnassert(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* value)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFHTMLBuilder(nsIRDFContentModelBuilder** result)
|
||||
{
|
||||
NS_PRECONDITION(result != nsnull, "null ptr");
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
RDFHTMLBuilderImpl* builder = new RDFHTMLBuilderImpl();
|
||||
if (! builder)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(builder);
|
||||
*result = builder;
|
||||
return NS_OK;
|
||||
}
|
||||
1416
mozilla/rdf/content/src/nsRDFResourceElement.cpp
Normal file
1416
mozilla/rdf/content/src/nsRDFResourceElement.cpp
Normal file
File diff suppressed because it is too large
Load Diff
757
mozilla/rdf/content/src/nsRDFTreeBuilder.cpp
Normal file
757
mozilla/rdf/content/src/nsRDFTreeBuilder.cpp
Normal file
@@ -0,0 +1,757 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An nsIRDFDocument implementation that builds a tree widget XUL
|
||||
content model that is to be used with a tree control.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIRDFContent.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Column);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title);
|
||||
|
||||
static const char* kColumnsTag = "COLUMNS";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFContentModelBuilderIID, NS_IRDFCONTENTMODELBUILDER_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RDFTreeBuilderImpl : public nsIRDFContentModelBuilder
|
||||
{
|
||||
private:
|
||||
nsIRDFDocument* mDocument;
|
||||
nsIRDFService* mRDFService;
|
||||
nsIRDFCompositeDataSource* mDB;
|
||||
|
||||
public:
|
||||
RDFTreeBuilderImpl();
|
||||
virtual ~RDFTreeBuilderImpl();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD CreateRoot(nsIRDFResource* aResource);
|
||||
NS_IMETHOD OnAssert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue);
|
||||
NS_IMETHOD OnUnassert(nsIRDFContent* aElement, nsIRDFResource* aProperty, nsIRDFNode* aValue);
|
||||
|
||||
|
||||
// Implementation methods
|
||||
|
||||
/**
|
||||
* Ensure that the specified tag exists as a child of the
|
||||
* parent element.
|
||||
*/
|
||||
nsresult
|
||||
EnsureChildElement(nsIContent* parent,
|
||||
nsIAtom* tag,
|
||||
nsIContent*& result);
|
||||
|
||||
/**
|
||||
* Add a new child to the content model from a tree property. This creates
|
||||
* the necessary cruft in the content model to ensure that content will
|
||||
* recursively be generated as the content model is descended.
|
||||
*/
|
||||
nsresult
|
||||
AddTreeChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value);
|
||||
|
||||
/**
|
||||
* Add a single column to the content model.
|
||||
*/
|
||||
nsresult
|
||||
AddColumn(nsIContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFLiteral* title);
|
||||
|
||||
|
||||
/**
|
||||
* Add columns to the content model from an RDF container (sequence or bag)
|
||||
*/
|
||||
nsresult
|
||||
AddColumnsFromContainer(nsIContent* parent,
|
||||
nsIRDFResource* columns);
|
||||
|
||||
|
||||
/**
|
||||
* Add columns to the content model from a set of multi-attributes
|
||||
*/
|
||||
nsresult
|
||||
AddColumnsFromMultiAttributes(nsIContent* parent,
|
||||
nsIRDFResource* columns);
|
||||
|
||||
/**
|
||||
* Add columns to the content model.
|
||||
*/
|
||||
nsresult
|
||||
AddColumns(nsIContent* parent,
|
||||
nsIRDFResource* columns);
|
||||
|
||||
/**
|
||||
* Add a new property element to the content model
|
||||
*/
|
||||
nsresult
|
||||
AddPropertyChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* value);
|
||||
|
||||
/**
|
||||
* Determine if the specified property on the content element is
|
||||
* a tree property.
|
||||
*/
|
||||
PRBool
|
||||
IsTreeProperty(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value);
|
||||
|
||||
/**
|
||||
* Determine if the specified property on the content element is
|
||||
* the root columns property.
|
||||
*/
|
||||
PRBool
|
||||
IsRootColumnsProperty(nsIRDFContent* parent,
|
||||
nsIRDFResource* property);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kOpenAtom;
|
||||
static nsIAtom* kFolderAtom;
|
||||
static nsIAtom* kChildrenAtom;
|
||||
static nsIAtom* kColumnsAtom;
|
||||
|
||||
nsresult
|
||||
NS_NewRDFTreeBuilder(nsIRDFContentModelBuilder** result)
|
||||
{
|
||||
NS_PRECONDITION(result != nsnull, "null ptr");
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
RDFTreeBuilderImpl* builder = new RDFTreeBuilderImpl();
|
||||
if (! builder)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(builder);
|
||||
*result = builder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RDFTreeBuilderImpl::RDFTreeBuilderImpl(void)
|
||||
{
|
||||
if (nsnull == kIdAtom) {
|
||||
kIdAtom = NS_NewAtom("ID");
|
||||
kOpenAtom = NS_NewAtom("OPEN");
|
||||
kFolderAtom = NS_NewAtom("FOLDER");
|
||||
kChildrenAtom = NS_NewAtom("CHILDREN");
|
||||
kColumnsAtom = NS_NewAtom("COLUMNS");
|
||||
}
|
||||
else {
|
||||
NS_ADDREF(kIdAtom);
|
||||
NS_ADDREF(kOpenAtom);
|
||||
NS_ADDREF(kFolderAtom);
|
||||
NS_ADDREF(kChildrenAtom);
|
||||
NS_ADDREF(kColumnsAtom);
|
||||
}
|
||||
}
|
||||
|
||||
RDFTreeBuilderImpl::~RDFTreeBuilderImpl(void)
|
||||
{
|
||||
NS_IF_RELEASE(mDB);
|
||||
|
||||
if (mRDFService)
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService);
|
||||
|
||||
nsrefcnt refcnt;
|
||||
NS_RELEASE2(kIdAtom, refcnt);
|
||||
NS_RELEASE2(kOpenAtom, refcnt);
|
||||
NS_RELEASE2(kFolderAtom, refcnt);
|
||||
NS_RELEASE2(kChildrenAtom, refcnt);
|
||||
NS_RELEASE2(kColumnsAtom, refcnt);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFTreeBuilderImpl, kIRDFContentModelBuilderIID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFContentModelBuilder methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFTreeBuilderImpl::SetDocument(nsIRDFDocument* aDocument)
|
||||
{
|
||||
NS_PRECONDITION(aDocument != nsnull, "null ptr");
|
||||
if (! aDocument)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mDocument = aDocument; // not refcounted
|
||||
|
||||
nsresult rv;
|
||||
if (NS_FAILED(rv = mDocument->GetDataBase(mDB)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &mRDFService)))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFTreeBuilderImpl::CreateRoot(nsIRDFResource* aResource)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIAtom* tag = nsnull;
|
||||
nsIRDFContent* root = nsnull;
|
||||
nsIDocument* doc = nsnull;
|
||||
|
||||
if ((tag = NS_NewAtom("ROOT")) == nsnull)
|
||||
goto done;
|
||||
|
||||
// PR_TRUE indicates that children should be recursively generated on demand
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&root, aResource, kNameSpaceID_None, tag, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->QueryInterface(kIDocumentIID, (void**) &doc)))
|
||||
goto done;
|
||||
|
||||
doc->SetRootContent(root);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(doc);
|
||||
NS_IF_RELEASE(root);
|
||||
NS_IF_RELEASE(tag);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFTreeBuilderImpl::OnAssert(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* value)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIRDFResource* resource;
|
||||
|
||||
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
|
||||
if (IsRootColumnsProperty(parent, property)) {
|
||||
rv = AddColumns(parent, resource);
|
||||
NS_RELEASE(resource);
|
||||
return rv;
|
||||
}
|
||||
else if (IsTreeProperty(parent, property, resource)) {
|
||||
rv = AddTreeChild(parent, property, resource);
|
||||
NS_RELEASE(resource);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// fall through and add as a property
|
||||
NS_RELEASE(resource);
|
||||
}
|
||||
|
||||
rv = AddPropertyChild(parent, property, value);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFTreeBuilderImpl::OnUnassert(nsIRDFContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aValue)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation methods
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::EnsureChildElement(nsIContent* parent,
|
||||
nsIAtom* tag,
|
||||
nsIContent*& result)
|
||||
{
|
||||
nsresult rv;
|
||||
result = nsnull; // reasonable default
|
||||
|
||||
PRInt32 count;
|
||||
if (NS_FAILED(rv = parent->ChildCount(count)))
|
||||
return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsIContent* kid;
|
||||
if (NS_FAILED(rv = parent->ChildAt(i, kid)))
|
||||
break;
|
||||
|
||||
nsIAtom* kidTag;
|
||||
if (NS_FAILED(rv = kid->GetTag(kidTag))) {
|
||||
NS_RELEASE(kid);
|
||||
break;
|
||||
}
|
||||
|
||||
if (kidTag == tag) {
|
||||
NS_RELEASE(kidTag);
|
||||
result = kid; // no need to addref, got it from ChildAt().
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_RELEASE(kidTag);
|
||||
NS_RELEASE(kid);
|
||||
}
|
||||
|
||||
nsIContent* element = nsnull;
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
goto done;
|
||||
|
||||
// if we get here, we need to construct a new <children> element.
|
||||
|
||||
// XXX no namespace?
|
||||
if (NS_FAILED(rv = NS_NewRDFGenericElement(&element, kNameSpaceID_None, tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = parent->AppendChildTo(element, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
result = element;
|
||||
NS_ADDREF(result);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(element);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddTreeChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value)
|
||||
{
|
||||
// If it's a tree property, then we need to add the new child
|
||||
// element to a special "children" element in the parent. The
|
||||
// child element's value will be the value of the
|
||||
// property. We'll also attach an "ID=" attribute to the new
|
||||
// child; e.g.,
|
||||
//
|
||||
// <parent>
|
||||
// ...
|
||||
// <children>
|
||||
// <item id="value">
|
||||
// <!-- recursively generated -->
|
||||
// </item>
|
||||
// </children>
|
||||
// ...
|
||||
// </parent>
|
||||
|
||||
nsresult rv;
|
||||
nsIRDFContent* child = nsnull;
|
||||
nsIContent* children = nsnull;
|
||||
const char* p;
|
||||
|
||||
// Ensure that the <children> element exists on the parent.
|
||||
if (NS_FAILED(rv = EnsureChildElement(parent, kChildrenAtom, children)))
|
||||
goto done;
|
||||
|
||||
// Create a new child that represents the "value"
|
||||
// resource. PR_TRUE indicates that we want the child to
|
||||
// dynamically generate its own kids.
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&child, value, kNameSpaceID_None, kFolderAtom, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = value->GetValue(&p)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = child->SetAttribute(kNameSpaceID_HTML, kIdAtom, p, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
#define ALL_NODES_OPEN_HACK
|
||||
#ifdef ALL_NODES_OPEN_HACK
|
||||
if (NS_FAILED(rv = child->SetAttribute(kNameSpaceID_None, kOpenAtom, "TRUE", PR_FALSE)))
|
||||
goto done;
|
||||
#endif
|
||||
|
||||
// Finally, add the thing to the <children> element.
|
||||
children->AppendChildTo(child, PR_TRUE);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(child);
|
||||
NS_IF_RELEASE(children);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddColumn(nsIContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFLiteral* title)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 nameSpaceID;
|
||||
nsIAtom* tag = nsnull;
|
||||
nsIContent* column = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, &tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFGenericElement(&column, nameSpaceID, tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = parent->AppendChildTo(column, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
rv = rdf_AttachTextNode(column, title);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(tag);
|
||||
NS_IF_RELEASE(column);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
When columns are specified using a container, the data model is
|
||||
assumed to look something like the following example:
|
||||
|
||||
<RDF:RDF>
|
||||
<RDF:Description RDF:about="nc:history">
|
||||
<NC:Columns>
|
||||
<RDF:Seq>
|
||||
<RDF:li>
|
||||
<NC:Description
|
||||
NC:Column="http://home.netscape.com/NC-rdf#LastVisitDate"
|
||||
NC:Title="Date Last Visited"/>
|
||||
</RDF:li>
|
||||
|
||||
<RDF:li>
|
||||
<NC:Description
|
||||
NC:Column="http://home.netscape.com/NC-rdf#URL"
|
||||
NC:Title="URL"/>
|
||||
</RDF:li>
|
||||
|
||||
<RDF:li>
|
||||
<NC:Description
|
||||
NC:Column="http://home.netscape.com/NC-rdf#Title"
|
||||
NC:Title="Title"/>
|
||||
</RDF:li>
|
||||
</RDF:Seq>
|
||||
</NC:Columns>
|
||||
|
||||
<!-- ...whatever... -->
|
||||
|
||||
</RDF:Description>
|
||||
</RDF:RDF>
|
||||
|
||||
*/
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddColumnsFromContainer(nsIContent* parent,
|
||||
nsIRDFResource* columns)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsIContent* columnsElement;
|
||||
if (NS_FAILED(rv = EnsureChildElement(parent, kColumnsAtom, columnsElement)))
|
||||
return rv;
|
||||
|
||||
nsIRDFResource* NC_Column = nsnull;
|
||||
nsIRDFResource* NC_Title = nsnull;
|
||||
nsIRDFAssertionCursor* cursor = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = mRDFService->GetResource(kURINC_Column, &NC_Column)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = mRDFService->GetResource(kURINC_Title, &NC_Title)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewContainerCursor(mDB, columns, &cursor)))
|
||||
goto done;
|
||||
|
||||
while (NS_SUCCEEDED(rv = cursor->Advance())) {
|
||||
nsIRDFNode* columnNode;
|
||||
if (NS_SUCCEEDED(rv = cursor->GetObject(&columnNode))) {
|
||||
nsIRDFResource* column;
|
||||
if (NS_SUCCEEDED(rv = columnNode->QueryInterface(kIRDFResourceIID, (void**) &column))) {
|
||||
// XXX okay, error recovery leaves a bit to be desired here...
|
||||
nsIRDFNode* propertyNode = nsnull;
|
||||
nsIRDFResource* property = nsnull;
|
||||
nsIRDFNode* titleNode = nsnull;
|
||||
nsIRDFLiteral* title = nsnull;
|
||||
|
||||
rv = mDB->GetTarget(column, NC_Column, PR_TRUE, &propertyNode);
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = propertyNode->QueryInterface(kIRDFResourceIID, (void**) &property);
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = mDB->GetTarget(column, NC_Title, PR_TRUE, &titleNode);
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = titleNode->QueryInterface(kIRDFLiteralIID, (void**) &title);
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
AddColumn(columnsElement, property, title);
|
||||
|
||||
NS_IF_RELEASE(title);
|
||||
NS_IF_RELEASE(titleNode);
|
||||
NS_IF_RELEASE(property);
|
||||
NS_IF_RELEASE(propertyNode);
|
||||
|
||||
NS_RELEASE(column);
|
||||
}
|
||||
NS_RELEASE(columnNode);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
|
||||
// This is a "normal" return code from nsIRDFCursor::Advance().
|
||||
rv = NS_OK;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(cursor);
|
||||
NS_IF_RELEASE(NC_Title);
|
||||
NS_IF_RELEASE(NC_Column);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
When the columns are specified using multi-attributes, the data
|
||||
model assumed to look something like the following example:
|
||||
|
||||
<RDF:RDF>
|
||||
<RDF:Description RDF:about="nc:history">
|
||||
<NC:Columns>
|
||||
<NC:LastVisitDate RDF:ID="#001">Date Last Visited</NC:LastVisitDate>
|
||||
<NC:URL RDF:ID="#002">URL</NC:URL>
|
||||
<NC:Title RDF:ID="#003">Title</NC:URL>
|
||||
<NC:Order>
|
||||
<RDF:Seq>
|
||||
<RDF:li RDF:resource="#003"/>
|
||||
<RDF:li RDF:resource="#002"/>
|
||||
<RDF:li RDF:resource="#001"/>
|
||||
</RDF:Seq>
|
||||
</NC:Order>
|
||||
</NC:Columns>
|
||||
|
||||
<!-- ...whatever... -->
|
||||
|
||||
</RDF:Description>
|
||||
</RDF:RDF>
|
||||
|
||||
TODO: implement the NC:Order property on the column set. This is not
|
||||
exactly a slam dunk; it requires getting reification working
|
||||
properly in the RDF content sink.
|
||||
|
||||
*/
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddColumnsFromMultiAttributes(nsIContent* parent,
|
||||
nsIRDFResource* columns)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsIContent* columnsElement;
|
||||
if (NS_FAILED(rv = EnsureChildElement(parent, kColumnsAtom, columnsElement)))
|
||||
return rv;
|
||||
|
||||
nsIRDFArcsOutCursor* cursor = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = mDB->ArcLabelsOut(columns, &cursor)))
|
||||
goto done;
|
||||
|
||||
while (NS_SUCCEEDED(rv = cursor->Advance())) {
|
||||
nsIRDFResource* property;
|
||||
if (NS_SUCCEEDED(rv = cursor->GetPredicate(&property))) {
|
||||
nsIRDFNode* titleNode;
|
||||
if (NS_SUCCEEDED(rv = mDB->GetTarget(columns, property, PR_TRUE, &titleNode))) {
|
||||
nsIRDFLiteral* title;
|
||||
if (NS_SUCCEEDED(rv = titleNode->QueryInterface(kIRDFLiteralIID,
|
||||
(void**) &title))) {
|
||||
rv = AddColumn(columnsElement, property, title);
|
||||
NS_RELEASE(title);
|
||||
}
|
||||
NS_RELEASE(titleNode);
|
||||
}
|
||||
NS_RELEASE(property);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ASSERTION(rv == NS_ERROR_RDF_CURSOR_EMPTY, "error reading from cursor");
|
||||
if (rv == NS_ERROR_RDF_CURSOR_EMPTY)
|
||||
// This is a reasonable return code from nsIRDFCursor::Advance()
|
||||
rv = NS_OK;
|
||||
|
||||
// XXX Now search for an "order" property and apply it to the
|
||||
// above to sort them...
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(cursor);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddColumns(nsIContent* parent,
|
||||
nsIRDFResource* columns)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (rdf_IsContainer(mDB, columns)) {
|
||||
rv = AddColumnsFromContainer(parent, columns);
|
||||
}
|
||||
else {
|
||||
rv = AddColumnsFromMultiAttributes(parent, columns);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFTreeBuilderImpl::AddPropertyChild(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* value)
|
||||
{
|
||||
// Otherwise, it's not a tree property. So we'll just create a
|
||||
// new element for the property, and a simple text node for
|
||||
// its value; e.g.,
|
||||
//
|
||||
// <parent>
|
||||
// <columns>
|
||||
// <folder>value</folder>
|
||||
// </columns>
|
||||
// ...
|
||||
// </parent>
|
||||
nsresult rv;
|
||||
nsIContent* columnsElement = nsnull;
|
||||
nsIRDFContent* child = nsnull;
|
||||
PRInt32 nameSpaceID;
|
||||
nsIAtom* tag = nsnull;
|
||||
|
||||
if (NS_FAILED(rv = EnsureChildElement(parent, kColumnsAtom, columnsElement)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, &tag)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = NS_NewRDFResourceElement(&child, property, nameSpaceID, tag, PR_FALSE)))
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(rv = columnsElement->AppendChildTo(child, PR_TRUE)))
|
||||
goto done;
|
||||
|
||||
rv = rdf_AttachTextNode(child, value);
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(tag);
|
||||
NS_IF_RELEASE(columnsElement);
|
||||
NS_IF_RELEASE(child);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
RDFTreeBuilderImpl::IsTreeProperty(nsIRDFContent* parent,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFResource* value)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRBool isTreeProperty = PR_FALSE;
|
||||
if (NS_FAILED(rv = mDocument->IsTreeProperty(property, &isTreeProperty)))
|
||||
goto done;
|
||||
|
||||
if (isTreeProperty)
|
||||
goto done;
|
||||
|
||||
isTreeProperty = rdf_IsContainer(mDB, value);
|
||||
|
||||
done:
|
||||
return isTreeProperty;
|
||||
}
|
||||
|
||||
PRBool
|
||||
RDFTreeBuilderImpl::IsRootColumnsProperty(nsIRDFContent* parent,
|
||||
nsIRDFResource* property)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsIDocument* doc = nsnull;
|
||||
nsIContent* rootContent = nsnull;
|
||||
|
||||
PRBool isColumnsProperty = PR_FALSE;;
|
||||
|
||||
if (NS_FAILED(rv = mDocument->QueryInterface(kIDocumentIID, (void**) &doc)))
|
||||
goto done;
|
||||
|
||||
if ((rootContent = doc->GetRootContent()) == nsnull)
|
||||
goto done;
|
||||
|
||||
if (parent != rootContent)
|
||||
goto done;
|
||||
|
||||
if (NS_FAILED(property->EqualsString(kURINC_Columns, &isColumnsProperty)))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
NS_IF_RELEASE(rootContent);
|
||||
NS_IF_RELEASE(doc);
|
||||
return isColumnsProperty;
|
||||
}
|
||||
29
mozilla/rdf/datasource/Makefile.in
Normal file
29
mozilla/rdf/datasource/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public src
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
27
mozilla/rdf/datasource/makefile.win
Normal file
27
mozilla/rdf/datasource/makefile.win
Normal file
@@ -0,0 +1,27 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
DIRS=\
|
||||
public \
|
||||
src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
2
mozilla/rdf/datasource/public/MANIFEST
Normal file
2
mozilla/rdf/datasource/public/MANIFEST
Normal file
@@ -0,0 +1,2 @@
|
||||
nsIRDFMail.h
|
||||
|
||||
35
mozilla/rdf/datasource/public/Makefile.in
Normal file
35
mozilla/rdf/datasource/public/Makefile.in
Normal file
@@ -0,0 +1,35 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
EXPORTS = \
|
||||
nsIRDFMail.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
28
mozilla/rdf/datasource/public/makefile.win
Normal file
28
mozilla/rdf/datasource/public/makefile.win
Normal file
@@ -0,0 +1,28 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
|
||||
MODULE=rdf
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
EXPORTS = \
|
||||
nsIRDFMail.h \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
56
mozilla/rdf/datasource/public/nsIRDFHistory.h
Normal file
56
mozilla/rdf/datasource/public/nsIRDFHistory.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFHistory_h__
|
||||
#define nsIRDFHistory_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
// {115CE051-A59D-11d2-80B6-006097B76B8E}
|
||||
#define NS_IRDFWEBPAGE_IID \
|
||||
{ 0x115ce051, 0xa59d, 0x11d2, { 0x80, 0xb6, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } };
|
||||
|
||||
// {1A880051-A59D-11d2-80B6-006097B76B8E}
|
||||
#define NS_IRDFHISTORYDATASOURCE_IID \
|
||||
{ 0x1a880051, 0xa59d, 0x11d2, { 0x80, 0xb6, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } };
|
||||
|
||||
|
||||
class nsIRDFHistoryDataSource : public nsIRDFDataSource {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Add the specified item to history
|
||||
*/
|
||||
NS_IMETHOD AddPage (const char* uri) = 0;
|
||||
|
||||
/**
|
||||
* Set the title of the page
|
||||
*/
|
||||
NS_IMETHOD SetPageTitle (const char* uri, PRUnichar* title) = 0;
|
||||
|
||||
/**
|
||||
* Remove the page from history
|
||||
*/
|
||||
NS_IMETHOD RemovePage (nsIRDFResource* page) = 0;
|
||||
|
||||
/**
|
||||
* Get the uri's last visit date
|
||||
*/
|
||||
NS_IMETHOD LastVisitDate (const char* uri, unit32 *date) = 0;
|
||||
};
|
||||
128
mozilla/rdf/datasource/public/nsIRDFMail.h
Normal file
128
mozilla/rdf/datasource/public/nsIRDFMail.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsIRDFMail_h__
|
||||
#define nsIRDFMail_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
/*
|
||||
Interfaces for the mail data source.
|
||||
|
||||
The UI will interact with the mail data source via the
|
||||
nsIRDFDataSource interface. The following methods are mostly for
|
||||
netlib to talk to the database. It needs to be able to add/delete an
|
||||
account, folder or message.
|
||||
*/
|
||||
|
||||
// {669F3361-9EAF-11d2-80B4-006097B76B8E}
|
||||
#define NS_IRDFMAILDATAOURCE_IID \
|
||||
{ 0x669f3361, 0x9eaf, 0x11d2, { 0x80, 0xb4, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } }
|
||||
|
||||
class nsIRDFMailAccount;
|
||||
class nsIRDFMailFolder;
|
||||
class nsIRDFMailMessage;
|
||||
|
||||
class nsIRDFMailDataSource : public nsIRDFDataSource {
|
||||
public:
|
||||
/**
|
||||
* Add the specified mail account to the data source.
|
||||
*/
|
||||
NS_IMETHOD AddAccount (nsIRDFMailAccount* folder) = 0;
|
||||
|
||||
/**
|
||||
* Remove the specified mail account from the data source.
|
||||
*/
|
||||
NS_IMETHOD RemoveAccount (nsIRDFMailAccount* folder) = 0;
|
||||
};
|
||||
|
||||
// {9D2792E0-9EAE-11d2-80B4-006097B76B8E}
|
||||
#define NS_IMAILACCOUNT_IID \
|
||||
{ 0x9d2792e0, 0x9eae, 0x11d2, { 0x80, 0xb4, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } }
|
||||
|
||||
/**
|
||||
* A resource specialization for mail accounts.
|
||||
*/
|
||||
class nsIRDFMailAccount : public nsIRDFResource {
|
||||
public:
|
||||
|
||||
NS_IMETHOD GetUser(nsIRDFLiteral** result) const = 0;
|
||||
|
||||
NS_IMETHOD GetHost(nsIRDFLiteral** result) const = 0;
|
||||
|
||||
NS_IMETHOD GetName(nsIRDFLiteral** result) const = 0;
|
||||
|
||||
NS_IMETHOD AddFolder (nsIRDFMailFolder* folder) = 0;
|
||||
|
||||
NS_IMETHOD RemoveFolder (nsIRDFMailFolder* folder) = 0;
|
||||
};
|
||||
|
||||
// {9D2792E1-9EAE-11d2-80B4-006097B76B8E}
|
||||
#define NS_IMAILFOLDER_IID \
|
||||
{ 0x9d2792e1, 0x9eae, 0x11d2, { 0x80, 0xb4, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } }
|
||||
|
||||
/**
|
||||
* A resource specialization for mail folders.
|
||||
*/
|
||||
class nsIRDFMailFolder : public nsIRDFResource {
|
||||
public:
|
||||
|
||||
NS_IMETHOD GetAccount(nsIRDFMailAccount** account) = 0;
|
||||
|
||||
NS_IMETHOD GetName(nsIRDFLiteral** result) const = 0;
|
||||
|
||||
NS_IMETHOD GetMessageList (nsVoidArray** result) = 0;
|
||||
|
||||
NS_IMETHOD AddMessage (nsIRDFMailMessage* msg) = 0;
|
||||
|
||||
NS_IMETHOD RemoveMessage (nsIRDFMailMessage* msg) = 0;
|
||||
};
|
||||
|
||||
// {9D2792E2-9EAE-11d2-80B4-006097B76B8E}
|
||||
#define NS_IMAILMESSAGE_IID \
|
||||
{ 0x9d2792e2, 0x9eae, 0x11d2, { 0x80, 0xb4, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } }
|
||||
|
||||
/**
|
||||
* A resource specialization for mail messages.
|
||||
*/
|
||||
class nsIRDFMailMessage : public nsIRDFResource {
|
||||
public:
|
||||
|
||||
NS_IMETHOD GetFolder(nsIRDFMailFolder** account) = 0;
|
||||
|
||||
NS_IMETHOD GetSubject(nsIRDFLiteral** result) = 0;
|
||||
|
||||
NS_IMETHOD GetSender(nsIRDFResource** result) = 0;
|
||||
|
||||
NS_IMETHOD GetDate(nsIRDFLiteral** result) = 0;
|
||||
|
||||
NS_IMETHOD GetContent(const char* result) = 0;
|
||||
|
||||
NS_IMETHOD GetMessageID(nsIRDFLiteral** id) = 0;
|
||||
|
||||
// XXX this really sucks --- the flags, such as replied, forwarded, read, etc.
|
||||
// should have separate methods
|
||||
NS_IMETHOD GetFlags(char** result) = 0;
|
||||
|
||||
NS_IMETHOD SetFlags(const char* result) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif nsIRDFMail_h
|
||||
54
mozilla/rdf/datasource/src/Makefile.in
Normal file
54
mozilla/rdf/datasource/src/Makefile.in
Normal file
@@ -0,0 +1,54 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBRARY_NAME = rdfdatasource_s
|
||||
|
||||
CPPSRCS = \
|
||||
nsBookmarkDataSource.cpp \
|
||||
nsMailDataSource.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
MODULE = rdf
|
||||
|
||||
REQUIRES = dom js netlib rdf raptor xpcom
|
||||
|
||||
# XXX This is a dependency on rdfutil.h: it'll go away once that becomes
|
||||
# a first-class XPCOM interface.
|
||||
INCLUDES += -I$(srcdir)/../../base/src
|
||||
|
||||
MKSHLIB :=
|
||||
|
||||
# we don't want the shared lib
|
||||
NO_SHARED_LIB=1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
50
mozilla/rdf/datasource/src/makefile.win
Normal file
50
mozilla/rdf/datasource/src/makefile.win
Normal file
@@ -0,0 +1,50 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=rdf
|
||||
LIBRARY_NAME=rdfdatasource_s
|
||||
|
||||
CPP_OBJS=\
|
||||
.\$(OBJDIR)\nsBookmarkDataSource.obj \
|
||||
.\$(OBJDIR)\nsMailDataSource.obj \
|
||||
$(NULL)
|
||||
|
||||
# XXX Note the dependency on $(DEPTH)\rdf\base\src: we use rdfutil.h over
|
||||
# in this library: this'll go away once we formalize utilities into an
|
||||
# "real live" XPCOM interface.
|
||||
|
||||
LINCS= -I$(PUBLIC)\rdf \
|
||||
-I$(PUBLIC)\xpcom \
|
||||
-I$(PUBLIC)\netlib \
|
||||
-I$(PUBLIC)\raptor \
|
||||
-I$(PUBLIC)\js \
|
||||
-I$(PUBLIC)\dom \
|
||||
-I$(DEPTH)\rdf\base\src \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
libs:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
|
||||
|
||||
|
||||
723
mozilla/rdf/datasource/src/nsBookmarkDataSource.cpp
Normal file
723
mozilla/rdf/datasource/src/nsBookmarkDataSource.cpp
Normal file
@@ -0,0 +1,723 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A data source that reads the 4.x "bookmarks.html" file and
|
||||
constructs an in-memory data source.
|
||||
|
||||
TO DO
|
||||
|
||||
1) Write the modified bookmarks file back to disk.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "prio.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
static const char kURINC_BookmarksRoot[] = "NC:BookmarksRoot"; // XXX?
|
||||
|
||||
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkAddDate);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Description);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, PersonalToolbarFolderCategory);
|
||||
|
||||
|
||||
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
|
||||
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate);
|
||||
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate);
|
||||
|
||||
|
||||
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
|
||||
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf);
|
||||
|
||||
static const char kPersonalToolbar[] = "Personal Toolbar";
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The bookmark parser knows how to read <tt>bookmarks.html</tt> and convert it
|
||||
* into an RDF graph.
|
||||
*/
|
||||
class BookmarkParser {
|
||||
protected:
|
||||
static const char* kBRString;
|
||||
static const char* kCloseDLString;
|
||||
static const char* kDDString;
|
||||
static const char* kOpenAnchorString;
|
||||
static const char* kOpenDLString;
|
||||
static const char* kOpenH3String;
|
||||
static const char* kOpenTitleString;
|
||||
static const char* kSeparatorString;
|
||||
|
||||
enum BookmarkParserState {
|
||||
eBookmarkParserState_Initial,
|
||||
eBookmarkParserState_InTitle,
|
||||
eBookmarkParserState_InH3,
|
||||
eBookmarkParserState_InItemTitle,
|
||||
eBookmarkParserState_InItemDescription
|
||||
};
|
||||
|
||||
nsIRDFService* mRDFService;
|
||||
nsIRDFDataSource* mDataSource;
|
||||
nsVoidArray mStack;
|
||||
nsIRDFResource* mLastItem;
|
||||
nsAutoString mLine;
|
||||
PRInt32 mCounter;
|
||||
nsAutoString mFolderDate;
|
||||
BookmarkParserState mState;
|
||||
|
||||
void Tokenize(const char* buf, PRInt32 size);
|
||||
void NextToken(void);
|
||||
void DoStateTransition(void);
|
||||
void CreateBookmark(void);
|
||||
|
||||
nsresult AssertTime(nsIRDFResource* subject,
|
||||
const nsString& predicateURI,
|
||||
const nsString& time);
|
||||
|
||||
public:
|
||||
BookmarkParser(void);
|
||||
~BookmarkParser();
|
||||
|
||||
nsresult Parse(PRFileDesc* file, nsIRDFDataSource* dataSource);
|
||||
};
|
||||
|
||||
|
||||
const char* BookmarkParser::kBRString = "<BR>";
|
||||
const char* BookmarkParser::kCloseDLString = "</DL>";
|
||||
const char* BookmarkParser::kDDString = "<DD>";
|
||||
const char* BookmarkParser::kOpenAnchorString = "<A";
|
||||
const char* BookmarkParser::kOpenDLString = "<DL>";
|
||||
const char* BookmarkParser::kOpenH3String = "<H3";
|
||||
const char* BookmarkParser::kOpenTitleString = "<TITLE>";
|
||||
const char* BookmarkParser::kSeparatorString = "<HR>";
|
||||
|
||||
|
||||
BookmarkParser::BookmarkParser(void)
|
||||
: mRDFService(nsnull), mDataSource(nsnull)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &mRDFService);
|
||||
|
||||
PR_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
BookmarkParser::~BookmarkParser(void)
|
||||
{
|
||||
if (mRDFService)
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
BookmarkParser::Parse(PRFileDesc* file, nsIRDFDataSource* dataSource)
|
||||
{
|
||||
NS_PRECONDITION(file && dataSource && mRDFService, "null ptr");
|
||||
if (! file)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! dataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mRDFService)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// Initialize the parser for a run...
|
||||
mDataSource = dataSource;
|
||||
mState = eBookmarkParserState_Initial;
|
||||
mCounter = 0;
|
||||
mLastItem = nsnull;
|
||||
mLine.Truncate();
|
||||
|
||||
char buf[1024];
|
||||
PRInt32 len;
|
||||
|
||||
while ((len = PR_Read(file, buf, sizeof(buf))) > 0)
|
||||
Tokenize(buf, len);
|
||||
|
||||
NS_IF_RELEASE(mLastItem);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BookmarkParser::Tokenize(const char* buf, PRInt32 size)
|
||||
{
|
||||
for (PRInt32 i = 0; i < size; ++i) {
|
||||
char c = buf[i];
|
||||
if (c == '<') {
|
||||
if (mLine.Length() > 0) {
|
||||
NextToken();
|
||||
mLine.Truncate();
|
||||
}
|
||||
}
|
||||
mLine.Append(c);
|
||||
if (c == '>') {
|
||||
if (mLine.Length() > 0) {
|
||||
NextToken();
|
||||
mLine.Truncate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BookmarkParser::NextToken(void)
|
||||
{
|
||||
if (mLine[0] == '<') {
|
||||
DoStateTransition();
|
||||
return;
|
||||
}
|
||||
|
||||
// ok, we have a piece of content. can be the title, or a
|
||||
// description
|
||||
if ((mState == eBookmarkParserState_InTitle) ||
|
||||
(mState == eBookmarkParserState_InH3)) {
|
||||
nsIRDFResource* folder;
|
||||
|
||||
if (mStack.Count() > 0) {
|
||||
// a regular old folder
|
||||
|
||||
nsAutoString folderURI(kURINC_BookmarksRoot);
|
||||
folderURI.Append('#');
|
||||
folderURI.Append(++mCounter, 10);
|
||||
|
||||
if (NS_FAILED(mRDFService->GetUnicodeResource(folderURI, &folder)))
|
||||
return;
|
||||
|
||||
nsIRDFResource* parent = (nsIRDFResource*) mStack[mStack.Count() - 1];
|
||||
rdf_Assert(mDataSource, parent, kURINC_Folder, folder);
|
||||
}
|
||||
else {
|
||||
// it's the root
|
||||
if (NS_FAILED(mRDFService->GetResource(kURINC_BookmarksRoot, &folder)))
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFolderDate.Length()) {
|
||||
AssertTime(folder, kURINC_BookmarkAddDate, mFolderDate);
|
||||
mFolderDate.Truncate();
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mLastItem);
|
||||
mLastItem = folder;
|
||||
// XXX Implied
|
||||
//NS_ADDREF(mLastItem);
|
||||
//NS_RELEASE(folder);
|
||||
|
||||
if (mState != eBookmarkParserState_InTitle)
|
||||
rdf_Assert(mDataSource, mLastItem, kURINC_Name, mLine);
|
||||
|
||||
if (mLine.Find(kPersonalToolbar) == 0)
|
||||
rdf_Assert(mDataSource, mLastItem, kURIRDF_instanceOf, kURINC_PersonalToolbarFolderCategory);
|
||||
}
|
||||
else if (mState == eBookmarkParserState_InItemTitle) {
|
||||
PR_ASSERT(mLastItem);
|
||||
if (! mLastItem)
|
||||
return;
|
||||
|
||||
rdf_Assert(mDataSource, mLastItem, kURINC_Name, mLine);
|
||||
NS_IF_RELEASE(mLastItem);
|
||||
}
|
||||
else if (mState == eBookmarkParserState_InItemDescription) {
|
||||
rdf_Assert(mDataSource, mLastItem, kURINC_Description, mLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BookmarkParser::DoStateTransition(void)
|
||||
{
|
||||
if (mLine.Find(kOpenAnchorString) == 0) {
|
||||
CreateBookmark();
|
||||
mState = eBookmarkParserState_InItemTitle;
|
||||
}
|
||||
else if (mLine.Find(kOpenH3String) == 0) {
|
||||
PRInt32 start = mLine.Find('"');
|
||||
PRInt32 end = mLine.RFind('"');
|
||||
if (start >= 0 && end >= 0)
|
||||
mLine.Mid(mFolderDate, start + 1, end - start - 1);
|
||||
mState = eBookmarkParserState_InH3;
|
||||
}
|
||||
else if (mLine.Find(kOpenTitleString) == 0) {
|
||||
mState = eBookmarkParserState_InTitle;
|
||||
}
|
||||
else if (mLine.Find(kDDString) == 0) {
|
||||
#if 0 // XXX if it doesn't already have a description? Huh?
|
||||
if (remoteStoreGetSlotValue(gLocalStore, mLastItem, gWebData->RDF_description,
|
||||
RDF_STRING_TYPE, false, true)
|
||||
== nsnull)
|
||||
#endif
|
||||
mState = eBookmarkParserState_InItemDescription;
|
||||
}
|
||||
else if (mLine.Find(kOpenDLString) == 0) {
|
||||
mStack.AppendElement(mLastItem);
|
||||
NS_ADDREF(mLastItem);
|
||||
}
|
||||
else if (mLine.Find(kCloseDLString) == 0) {
|
||||
PRInt32 count = mStack.Count();
|
||||
if (count) {
|
||||
nsIRDFNode* top = NS_STATIC_CAST(nsIRDFNode*, mStack[--count]);
|
||||
mStack.RemoveElementAt(count);
|
||||
NS_IF_RELEASE(top);
|
||||
}
|
||||
}
|
||||
else if (mLine.Find(kSeparatorString) == 0) {
|
||||
#if FIXME // separators
|
||||
addSlotValue(f, createSeparator(), gCoreVocab->RDF_parent, mStack[mStack.Count() - 1],
|
||||
RDF_RESOURCE_TYPE, nsnull);
|
||||
#endif
|
||||
mState = eBookmarkParserState_Initial;
|
||||
}
|
||||
else if ((mState == eBookmarkParserState_InItemDescription) &&
|
||||
(mLine.Find(kBRString) == 0)) {
|
||||
// XXX in the original bmk2rdf.c, we only added the
|
||||
// description in the case that it wasn't set already...why?
|
||||
rdf_Assert(mDataSource, mLastItem, kURINC_Description, mLine);
|
||||
}
|
||||
else {
|
||||
mState = eBookmarkParserState_Initial;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
BookmarkParser::CreateBookmark(void)
|
||||
{
|
||||
enum {
|
||||
eBmkAttribute_URL = 0,
|
||||
eBmkAttribute_AddDate = 1,
|
||||
eBmkAttribute_LastVisit = 2,
|
||||
eBmkAttribute_LastModified = 3
|
||||
};
|
||||
|
||||
nsAutoString values[4];
|
||||
PRInt32 index = 0;
|
||||
for (PRInt32 i = 0; i < 4; ++i) {
|
||||
PRInt32 start = mLine.Find('"', index);
|
||||
if (start == -1)
|
||||
break;
|
||||
|
||||
++start; // past the first quote
|
||||
|
||||
PRInt32 end = mLine.Find('"', start);
|
||||
PR_ASSERT(end > 0); // unterminated
|
||||
if (end == -1)
|
||||
end = mLine.Length();
|
||||
|
||||
mLine.Mid(values[i], start, end - start);
|
||||
index = end + 1;
|
||||
}
|
||||
|
||||
if (values[eBmkAttribute_URL].Length() == 0)
|
||||
return;
|
||||
|
||||
nsIRDFResource* bookmark;
|
||||
if (NS_FAILED(mRDFService->GetUnicodeResource(values[eBmkAttribute_URL], &bookmark)))
|
||||
return;
|
||||
|
||||
if (! mStack.Count())
|
||||
return;
|
||||
|
||||
nsIRDFResource* parent = (nsIRDFResource*) mStack[mStack.Count() - 1];
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
rdf_Assert(mDataSource, parent, kURINC_child, bookmark);
|
||||
|
||||
if (values[eBmkAttribute_AddDate].Length() > 0)
|
||||
AssertTime(bookmark, kURINC_BookmarkAddDate, values[eBmkAttribute_AddDate]);
|
||||
|
||||
if (values[eBmkAttribute_LastVisit].Length() > 0)
|
||||
AssertTime(bookmark, kURIWEB_LastVisitDate, values[eBmkAttribute_LastVisit]);
|
||||
|
||||
if (values[eBmkAttribute_LastModified].Length() > 0)
|
||||
AssertTime(bookmark, kURIWEB_LastModifiedDate, values[eBmkAttribute_LastModified]);
|
||||
|
||||
NS_IF_RELEASE(mLastItem);
|
||||
mLastItem = bookmark;
|
||||
// XXX Implied
|
||||
//NS_ADDREF(mLastItem);
|
||||
//NS_RELEASE(bookmark);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
BookmarkParser::AssertTime(nsIRDFResource* object,
|
||||
const nsString& predicateURI,
|
||||
const nsString& time)
|
||||
{
|
||||
// XXX
|
||||
return rdf_Assert(mDataSource, object, predicateURI, time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// BookmarkDataSourceImpl
|
||||
|
||||
/**
|
||||
* The bookmark data source uses a <tt>BookmarkParser</tt> to read the
|
||||
* <tt>bookmarks.html</tt> file from the local disk and present an
|
||||
* in-memory RDF graph based on it.
|
||||
*/
|
||||
class BookmarkDataSourceImpl : public nsIRDFDataSource {
|
||||
protected:
|
||||
static const char* kBookmarksFilename;
|
||||
|
||||
nsIRDFDataSource* mInner;
|
||||
|
||||
nsresult ReadBookmarks(void);
|
||||
nsresult WriteBookmarks(void);
|
||||
nsresult AddColumns(void);
|
||||
|
||||
public:
|
||||
BookmarkDataSourceImpl(void);
|
||||
virtual ~BookmarkDataSourceImpl(void);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFDataSource
|
||||
NS_IMETHOD Init(const char* uri);
|
||||
|
||||
NS_IMETHOD GetURI(const char* *uri) const {
|
||||
return mInner->GetURI(uri);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source) {
|
||||
return mInner->GetSource(property, target, tv, source);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** sources) {
|
||||
return mInner->GetSources(property, target, tv, sources);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target) {
|
||||
return mInner->GetTarget(source, property, tv, target);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFAssertionCursor** targets) {
|
||||
return mInner->GetTargets(source, property, tv, targets);
|
||||
}
|
||||
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv) {
|
||||
return mInner->Assert(source, property, target, tv);
|
||||
}
|
||||
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target) {
|
||||
return mInner->Unassert(source, property, target);
|
||||
}
|
||||
|
||||
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion) {
|
||||
return mInner->HasAssertion(source, property, target, tv, hasAssertion);
|
||||
}
|
||||
|
||||
NS_IMETHOD AddObserver(nsIRDFObserver* n) {
|
||||
return mInner->AddObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) {
|
||||
return mInner->RemoveObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels) {
|
||||
return mInner->ArcLabelsIn(node, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels) {
|
||||
return mInner->ArcLabelsOut(source, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush(void);
|
||||
|
||||
NS_IMETHOD IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult);
|
||||
|
||||
NS_IMETHOD DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// XXX we should get this from prefs.
|
||||
#ifdef XP_MAC
|
||||
const char* BookmarkDataSourceImpl::kBookmarksFilename = "/usr/local/netscape/bin/res/rdf/bookmarks.html";
|
||||
#else
|
||||
const char* BookmarkDataSourceImpl::kBookmarksFilename = "res\\rdf\\bookmarks.html";
|
||||
#endif
|
||||
|
||||
BookmarkDataSourceImpl::BookmarkDataSourceImpl(void)
|
||||
{
|
||||
// XXX rvg there should be only one instance of this class.
|
||||
// this is actually true of all datasources.
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
BookmarkDataSourceImpl::~BookmarkDataSourceImpl(void)
|
||||
{
|
||||
// unregister this from the RDF service
|
||||
nsresult rv;
|
||||
nsIRDFService* rdfService;
|
||||
if (NS_SUCCEEDED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &rdfService))) {
|
||||
rdfService->UnregisterDataSource(this);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
||||
}
|
||||
Flush();
|
||||
NS_RELEASE(mInner);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BookmarkDataSourceImpl, kIRDFDataSourceIID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
BookmarkDataSourceImpl::Init(const char* uri)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFInMemoryDataSourceCID,
|
||||
nsnull,
|
||||
kIRDFDataSourceIID,
|
||||
(void**) &mInner)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = mInner->Init(uri)))
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = ReadBookmarks()))
|
||||
return rv;
|
||||
|
||||
// register this as a named data source with the RDF service
|
||||
nsIRDFService* rdfService;
|
||||
if (NS_SUCCEEDED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
kIRDFServiceIID,
|
||||
(nsISupports**) &rdfService))) {
|
||||
rdfService->RegisterDataSource(this);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BookmarkDataSourceImpl::Flush(void)
|
||||
{
|
||||
return WriteBookmarks();
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
BookmarkDataSourceImpl::IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BookmarkDataSourceImpl::DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget)
|
||||
{
|
||||
PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
BookmarkDataSourceImpl::ReadBookmarks(void)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
PRFileDesc* f;
|
||||
if ((f = PR_Open(kBookmarksFilename, PR_RDONLY, 0644)) != nsnull) {
|
||||
BookmarkParser parser;
|
||||
rv = parser.Parse(f, this);
|
||||
PR_Close(f);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
BookmarkDataSourceImpl::WriteBookmarks(void)
|
||||
{
|
||||
//PR_ASSERT(0);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#if FIXME
|
||||
|
||||
static const nsString&
|
||||
rdf_NumericDate(const nsString& url)
|
||||
{
|
||||
nsAutoString result;
|
||||
PRInt32 len = url.Length();
|
||||
PRInt32 index = 0;
|
||||
|
||||
while (index < len && url[index] < '0' && url[index] > '9')
|
||||
++index;
|
||||
|
||||
if (index >= len)
|
||||
return result;
|
||||
|
||||
while (index < len && url[index] >= '0' && url[index] <= '9')
|
||||
result.Append(url[index++]);
|
||||
|
||||
result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HT_WriteOutAsBookmarks1 (RDF rdf, PRFileDesc *fp, RDF_Resource u, RDF_Resource top, int indent)
|
||||
{
|
||||
RDF_Cursor c = RDF_GetSources(rdf, u, gCoreVocab->RDF_parent, RDF_RESOURCE_TYPE, true);
|
||||
RDF_Resource next;
|
||||
char *date, *name, *url;
|
||||
int loop;
|
||||
|
||||
if (c == nsnull) return;
|
||||
if (u == top) {
|
||||
name = RDF_GetResourceName(rdf, u);
|
||||
ht_rjcprintf(fp, "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n", nsnull);
|
||||
ht_rjcprintf(fp, "<!-- This is an automatically generated file.\n", nsnull);
|
||||
ht_rjcprintf(fp, "It will be read and overwritten.\n", nsnull);
|
||||
ht_rjcprintf(fp, "Do Not Edit! -->\n", nsnull);
|
||||
|
||||
ht_rjcprintf(fp, "<TITLE>%s</TITLE>\n", (name) ? name:"");
|
||||
ht_rjcprintf(fp, "<H1>%s</H1>\n<DL><p>\n", (name) ? name:"");
|
||||
}
|
||||
while ((next = RDF_NextValue(c)) != nsnull) {
|
||||
|
||||
url = resourceID(next);
|
||||
if (containerp(next) && (!startsWith("ftp:",url)) && (!startsWith("file:",url))
|
||||
&& (!startsWith("IMAP:", url)) && (!startsWith("nes:", url))
|
||||
&& (!startsWith("mail:", url)) && (!startsWith("cache:", url))
|
||||
&& (!startsWith("ldap:", url))) {
|
||||
for (loop=0; loop<indent; loop++) ht_rjcprintf(fp, " ", nsnull);
|
||||
|
||||
date = numericDate(resourceID(next));
|
||||
ht_rjcprintf(fp, "<DT><H3 ADD_DATE=\"%s\">", (date) ? date:"");
|
||||
if (date) freeMem(date);
|
||||
name = RDF_GetResourceName(rdf, next);
|
||||
ht_rjcprintf(fp, "%s</H3>\n", name);
|
||||
|
||||
for (loop=0; loop<indent; loop++) ht_rjcprintf(fp, " ", nsnull);
|
||||
ht_rjcprintf(fp, "<DL><p>\n", nsnull);
|
||||
HT_WriteOutAsBookmarks1(rdf, fp, next, top, indent+1);
|
||||
|
||||
for (loop=0; loop<indent; loop++) ht_rjcprintf(fp, " ", nsnull);
|
||||
|
||||
ht_rjcprintf(fp, "</DL><p>\n", nsnull);
|
||||
}
|
||||
else if (isSeparator(next)) {
|
||||
for (loop=0; loop<indent; loop++) ht_rjcprintf(fp, " ", nsnull);
|
||||
ht_rjcprintf(fp, "<HR>\n", nsnull);
|
||||
}
|
||||
else {
|
||||
char* bkAddDate = (char*)RDF_GetSlotValue(rdf, next,
|
||||
gNavCenter->RDF_bookmarkAddDate,
|
||||
RDF_STRING_TYPE, false, true);
|
||||
|
||||
for (loop=0; loop<indent; loop++) ht_rjcprintf(fp, " ", nsnull);
|
||||
|
||||
ht_rjcprintf(fp, "<DT><A HREF=\"%s\" ", resourceID(next));
|
||||
date = numericDate(bkAddDate);
|
||||
ht_rjcprintf(fp, "ADD_DATE=\"%s\" ", (date) ? date: "");
|
||||
if (date) freeMem(date);
|
||||
ht_rjcprintf(fp, "LAST_VISIT=\"%s\" ", resourceLastVisitDate(rdf, next));
|
||||
ht_rjcprintf(fp, "LAST_MODIFIED=\"%s\">", resourceLastModifiedDate(rdf, next));
|
||||
ht_rjcprintf(fp, "%s</A>\n", RDF_GetResourceName(rdf, next));
|
||||
|
||||
if (resourceDescription(rdf, next) != nsnull) {
|
||||
ht_rjcprintf(fp, "<DD>%s\n", resourceDescription(rdf, next));
|
||||
}
|
||||
}
|
||||
}
|
||||
RDF_DisposeCursor(c);
|
||||
if (u == top) {
|
||||
ht_rjcprintf(fp, "</DL>\n", nsnull);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
NS_NewRDFBookmarkDataSource(nsIRDFDataSource** result)
|
||||
{
|
||||
BookmarkDataSourceImpl* ds = new BookmarkDataSourceImpl();
|
||||
if (! ds)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = ds;
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
164
mozilla/rdf/datasource/src/nsHistoryDataSource.cpp
Normal file
164
mozilla/rdf/datasource/src/nsHistoryDataSource.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include <ctype.h> // for toupper()
|
||||
#include <stdio.h>
|
||||
#include "nscore.h"
|
||||
#include "nsIRDFCursor.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFResourceFactory.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h" // XXX introduces dependency on raptorbase
|
||||
#include "nsRDFCID.h"
|
||||
#include "rdfutil.h"
|
||||
#include "nsIRDFMail.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "plhash.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
#include "prio.h"
|
||||
|
||||
#include "nsMailDataSource.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Interface IDs
|
||||
|
||||
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
|
||||
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
|
||||
static NS_DEFINE_IID(kIRDFHistoryDataSourceIID, NS_IRDFHISTORYDATAOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
|
||||
static NS_DEFINE_IID(kIRDFResourceFactoryIID, NS_IRDFRESOURCEFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// RDF property & resource declarations
|
||||
|
||||
static const char kURIHistoryRoot[] = "HistoryRoot";
|
||||
|
||||
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Column);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Columns);
|
||||
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title);
|
||||
|
||||
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
|
||||
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate);
|
||||
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate);
|
||||
|
||||
|
||||
|
||||
class nsHistoryDataSource : public nsIHistoryDataSource {
|
||||
nsIRDFDataSource** mInner;
|
||||
nsVoidArray mFiles;
|
||||
|
||||
public:
|
||||
NS_IMETHOD Init(const char* uri) ;
|
||||
NS_IMETHOD GetURI(const char* *uri) {
|
||||
return mInner->GetURI(uri);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv, nsIRDFResource** source) {
|
||||
return mInner->GetSource(property, target, tv, source);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target, PRBool tv,
|
||||
nsIRDFAssertionCursor** sources) {
|
||||
return mInner->GetSources(property, target, tv, sources);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property, PRBool tv,
|
||||
nsIRDFNode** target) {
|
||||
return mInner->GetTarget(source, property, tv, target);
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property, PRBool tv,
|
||||
nsIRDFAssertionCursor** targets) {
|
||||
return mInner->GetTargets(source, property, tv, targets);
|
||||
}
|
||||
|
||||
NS_IMETHOD Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target, PRBool tv) {
|
||||
return mInner->Assert(source, property, target, tv);
|
||||
}
|
||||
|
||||
NS_IMETHOD Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property, nsIRDFNode* target) {
|
||||
return mInner->Unassert(source, property, target);
|
||||
}
|
||||
|
||||
NS_IMETHOD HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target, PRBool tv,
|
||||
PRBool* hasAssertion) {
|
||||
return mInner->HasAssertion(source, property, target, tv, hasAssertion);
|
||||
}
|
||||
|
||||
NS_IMETHOD AddObserver(nsIRDFObserver* n) {
|
||||
return mInner->AddObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) {
|
||||
return mInner->RemoveObserver(n);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
|
||||
nsIRDFArcsInCursor** labels) {
|
||||
return mInner->ArcLabelsIn(node, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
|
||||
nsIRDFArcsOutCursor** labels) {
|
||||
return mInner->ArcLabelsOut(source, labels);
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush() {
|
||||
return mInner->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHOD IsCommandEnabled(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget,
|
||||
PRBool* aResult) {
|
||||
return mInner->IsCommandEnabled(aCommand, aCommandTarget, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHOD DoCommand(const char* aCommand,
|
||||
nsIRDFResource* aCommandTarget) {
|
||||
return mInner->DoCommand(aCommand, aCommandTarget);
|
||||
}
|
||||
|
||||
};
|
||||
1510
mozilla/rdf/datasource/src/nsMailDataSource.cpp
Normal file
1510
mozilla/rdf/datasource/src/nsMailDataSource.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user