summaryrefslogtreecommitdiffstats
path: root/dom/xslt/base
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xslt/base')
-rw-r--r--dom/xslt/base/moz.build26
-rw-r--r--dom/xslt/base/txCore.h51
-rw-r--r--dom/xslt/base/txDouble.cpp215
-rw-r--r--dom/xslt/base/txErrorObserver.h41
-rw-r--r--dom/xslt/base/txExpandedName.cpp41
-rw-r--r--dom/xslt/base/txExpandedName.h70
-rw-r--r--dom/xslt/base/txExpandedNameMap.cpp104
-rw-r--r--dom/xslt/base/txExpandedNameMap.h203
-rw-r--r--dom/xslt/base/txList.cpp278
-rw-r--r--dom/xslt/base/txList.h161
-rw-r--r--dom/xslt/base/txLog.h24
-rw-r--r--dom/xslt/base/txNamespaceMap.cpp98
-rw-r--r--dom/xslt/base/txNamespaceMap.h43
-rw-r--r--dom/xslt/base/txOwningArray.h32
-rw-r--r--dom/xslt/base/txStack.h122
-rw-r--r--dom/xslt/base/txStringUtils.h34
-rw-r--r--dom/xslt/base/txURIUtils.cpp78
-rw-r--r--dom/xslt/base/txURIUtils.h37
18 files changed, 1658 insertions, 0 deletions
diff --git a/dom/xslt/base/moz.build b/dom/xslt/base/moz.build
new file mode 100644
index 000000000..7d9cd70fa
--- /dev/null
+++ b/dom/xslt/base/moz.build
@@ -0,0 +1,26 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'txDouble.cpp',
+ 'txExpandedName.cpp',
+ 'txExpandedNameMap.cpp',
+ 'txList.cpp',
+ 'txNamespaceMap.cpp',
+ 'txURIUtils.cpp',
+]
+
+LOCAL_INCLUDES += [
+ '..',
+ '../xml',
+ '../xpath',
+ '../xslt',
+]
+
+FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']
diff --git a/dom/xslt/base/txCore.h b/dom/xslt/base/txCore.h
new file mode 100644
index 000000000..3bce3c089
--- /dev/null
+++ b/dom/xslt/base/txCore.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __txCore_h__
+#define __txCore_h__
+
+#include "nscore.h"
+#include "nsDebug.h"
+#include "nsISupportsImpl.h"
+
+class nsAString;
+
+class txObject
+{
+public:
+ txObject()
+ {
+ MOZ_COUNT_CTOR(txObject);
+ }
+
+ /**
+ * Deletes this txObject
+ */
+ virtual ~txObject()
+ {
+ MOZ_COUNT_DTOR(txObject);
+ }
+};
+
+/**
+ * Utility class for doubles
+ */
+class txDouble
+{
+public:
+ /**
+ * Converts the value of the given double to a string, and appends
+ * the result to the destination string.
+ */
+ static void toString(double aValue, nsAString& aDest);
+
+ /**
+ * Converts the given String to a double, if the string value does not
+ * represent a double, NaN will be returned.
+ */
+ static double toDouble(const nsAString& aStr);
+};
+
+#endif
diff --git a/dom/xslt/base/txDouble.cpp b/dom/xslt/base/txDouble.cpp
new file mode 100644
index 000000000..f52d1b885
--- /dev/null
+++ b/dom/xslt/base/txDouble.cpp
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/FloatingPoint.h"
+
+#include "nsString.h"
+#include "txCore.h"
+#include "txXMLUtils.h"
+#include <math.h>
+#include <stdlib.h>
+#include <algorithm>
+#ifdef WIN32
+#include <float.h>
+#endif
+#include "prdtoa.h"
+
+/*
+ * Utility class for doubles
+ */
+
+/*
+ * Converts the given String to a double, if the String value does not
+ * represent a double, NaN will be returned
+ */
+class txStringToDouble
+{
+public:
+ typedef char16_t input_type;
+ typedef char16_t value_type;
+ txStringToDouble(): mState(eWhitestart), mSign(ePositive) {}
+
+ void
+ write(const input_type* aSource, uint32_t aSourceLength)
+ {
+ if (mState == eIllegal) {
+ return;
+ }
+ uint32_t i = 0;
+ char16_t c;
+ for ( ; i < aSourceLength; ++i) {
+ c = aSource[i];
+ switch (mState) {
+ case eWhitestart:
+ if (c == '-') {
+ mState = eDecimal;
+ mSign = eNegative;
+ }
+ else if (c >= '0' && c <= '9') {
+ mState = eDecimal;
+ mBuffer.Append((char)c);
+ }
+ else if (c == '.') {
+ mState = eMantissa;
+ mBuffer.Append((char)c);
+ }
+ else if (!XMLUtils::isWhitespace(c)) {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eDecimal:
+ if (c >= '0' && c <= '9') {
+ mBuffer.Append((char)c);
+ }
+ else if (c == '.') {
+ mState = eMantissa;
+ mBuffer.Append((char)c);
+ }
+ else if (XMLUtils::isWhitespace(c)) {
+ mState = eWhiteend;
+ }
+ else {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eMantissa:
+ if (c >= '0' && c <= '9') {
+ mBuffer.Append((char)c);
+ }
+ else if (XMLUtils::isWhitespace(c)) {
+ mState = eWhiteend;
+ }
+ else {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eWhiteend:
+ if (!XMLUtils::isWhitespace(c)) {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ double
+ getDouble()
+ {
+ if (mState == eIllegal || mBuffer.IsEmpty() ||
+ (mBuffer.Length() == 1 && mBuffer[0] == '.')) {
+ return mozilla::UnspecifiedNaN<double>();
+ }
+ return mSign*PR_strtod(mBuffer.get(), 0);
+ }
+private:
+ nsAutoCString mBuffer;
+ enum {
+ eWhitestart,
+ eDecimal,
+ eMantissa,
+ eWhiteend,
+ eIllegal
+ } mState;
+ enum {
+ eNegative = -1,
+ ePositive = 1
+ } mSign;
+};
+
+double txDouble::toDouble(const nsAString& aSrc)
+{
+ txStringToDouble sink;
+ nsAString::const_iterator fromBegin, fromEnd;
+ copy_string(aSrc.BeginReading(fromBegin), aSrc.EndReading(fromEnd), sink);
+ return sink.getDouble();
+}
+
+/*
+ * Converts the value of the given double to a String, and places
+ * The result into the destination String.
+ * @return the given dest string
+ */
+void txDouble::toString(double aValue, nsAString& aDest)
+{
+
+ // check for special cases
+
+ if (mozilla::IsNaN(aValue)) {
+ aDest.AppendLiteral("NaN");
+ return;
+ }
+ if (mozilla::IsInfinite(aValue)) {
+ if (aValue < 0)
+ aDest.Append(char16_t('-'));
+ aDest.AppendLiteral("Infinity");
+ return;
+ }
+
+ // Mantissa length is 17, so this is plenty
+ const int buflen = 20;
+ char buf[buflen];
+
+ int intDigits, sign;
+ char* endp;
+ PR_dtoa(aValue, 0, 0, &intDigits, &sign, &endp, buf, buflen - 1);
+
+ // compute length
+ int32_t length = endp - buf;
+ if (length > intDigits) {
+ // decimal point needed
+ ++length;
+ if (intDigits < 1) {
+ // leading zeros, -intDigits + 1
+ length += 1 - intDigits;
+ }
+ }
+ else {
+ // trailing zeros, total length given by intDigits
+ length = intDigits;
+ }
+ if (aValue < 0)
+ ++length;
+ // grow the string
+ uint32_t oldlength = aDest.Length();
+ if (!aDest.SetLength(oldlength + length, mozilla::fallible))
+ return; // out of memory
+ nsAString::iterator dest;
+ aDest.BeginWriting(dest).advance(int32_t(oldlength));
+ if (aValue < 0) {
+ *dest = '-'; ++dest;
+ }
+ int i;
+ // leading zeros
+ if (intDigits < 1) {
+ *dest = '0'; ++dest;
+ *dest = '.'; ++dest;
+ for (i = 0; i > intDigits; --i) {
+ *dest = '0'; ++dest;
+ }
+ }
+ // mantissa
+ int firstlen = std::min<size_t>(intDigits, endp - buf);
+ for (i = 0; i < firstlen; i++) {
+ *dest = buf[i]; ++dest;
+ }
+ if (i < endp - buf) {
+ if (i > 0) {
+ *dest = '.'; ++dest;
+ }
+ for (; i < endp - buf; i++) {
+ *dest = buf[i]; ++dest;
+ }
+ }
+ // trailing zeros
+ for (; i < intDigits; i++) {
+ *dest = '0'; ++dest;
+ }
+}
diff --git a/dom/xslt/base/txErrorObserver.h b/dom/xslt/base/txErrorObserver.h
new file mode 100644
index 000000000..3c6be8294
--- /dev/null
+++ b/dom/xslt/base/txErrorObserver.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MITRE_ERROROBSERVER_H
+#define MITRE_ERROROBSERVER_H
+
+#include "txCore.h"
+
+/**
+ * A simple interface for observing errors
+**/
+class ErrorObserver {
+
+public:
+
+ /**
+ * Default Destructor for ErrorObserver
+ **/
+ virtual ~ErrorObserver() {};
+
+ /**
+ * Notifies this Error observer of a new error aRes
+ **/
+ virtual void receiveError(const nsAString& errorMessage, nsresult aRes) = 0;
+
+ /**
+ * Notifies this Error observer of a new error, with default
+ * error code NS_ERROR_FAILURE
+ **/
+ void receiveError(const nsAString& errorMessage)
+ {
+ receiveError(errorMessage, NS_ERROR_FAILURE);
+ }
+
+
+
+}; //-- ErrorObserver
+
+#endif
diff --git a/dom/xslt/base/txExpandedName.cpp b/dom/xslt/base/txExpandedName.cpp
new file mode 100644
index 000000000..43283e425
--- /dev/null
+++ b/dom/xslt/base/txExpandedName.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "txExpandedName.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "txStringUtils.h"
+#include "txNamespaceMap.h"
+#include "txXMLUtils.h"
+
+nsresult
+txExpandedName::init(const nsAString& aQName, txNamespaceMap* aResolver,
+ bool aUseDefault)
+{
+ const nsAFlatString& qName = PromiseFlatString(aQName);
+ const char16_t* colon;
+ bool valid = XMLUtils::isValidQName(qName, &colon);
+ if (!valid) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (colon) {
+ nsCOMPtr<nsIAtom> prefix = NS_Atomize(Substring(qName.get(), colon));
+ int32_t namespaceID = aResolver->lookupNamespace(prefix);
+ if (namespaceID == kNameSpaceID_Unknown)
+ return NS_ERROR_FAILURE;
+ mNamespaceID = namespaceID;
+
+ const char16_t *end;
+ qName.EndReading(end);
+ mLocalName = NS_Atomize(Substring(colon + 1, end));
+ }
+ else {
+ mNamespaceID = aUseDefault ? aResolver->lookupNamespace(nullptr) :
+ kNameSpaceID_None;
+ mLocalName = NS_Atomize(aQName);
+ }
+ return NS_OK;
+}
diff --git a/dom/xslt/base/txExpandedName.h b/dom/xslt/base/txExpandedName.h
new file mode 100644
index 000000000..b49fa5134
--- /dev/null
+++ b/dom/xslt/base/txExpandedName.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TRANSFRMX_EXPANDEDNAME_H
+#define TRANSFRMX_EXPANDEDNAME_H
+
+#include "nsCOMPtr.h"
+#include "nsIAtom.h"
+#include "mozilla/dom/NameSpaceConstants.h"
+
+class txNamespaceMap;
+
+class txExpandedName {
+public:
+ txExpandedName() : mNamespaceID(kNameSpaceID_None)
+ {
+ }
+
+ txExpandedName(int32_t aNsID,
+ nsIAtom* aLocalName) : mNamespaceID(aNsID),
+ mLocalName(aLocalName)
+ {
+ }
+
+ txExpandedName(const txExpandedName& aOther) :
+ mNamespaceID(aOther.mNamespaceID),
+ mLocalName(aOther.mLocalName)
+ {
+ }
+
+ nsresult init(const nsAString& aQName, txNamespaceMap* aResolver,
+ bool aUseDefault);
+
+ void reset()
+ {
+ mNamespaceID = kNameSpaceID_None;
+ mLocalName = nullptr;
+ }
+
+ bool isNull()
+ {
+ return mNamespaceID == kNameSpaceID_None && !mLocalName;
+ }
+
+ txExpandedName& operator = (const txExpandedName& rhs)
+ {
+ mNamespaceID = rhs.mNamespaceID;
+ mLocalName = rhs.mLocalName;
+ return *this;
+ }
+
+ bool operator == (const txExpandedName& rhs) const
+ {
+ return ((mLocalName == rhs.mLocalName) &&
+ (mNamespaceID == rhs.mNamespaceID));
+ }
+
+ bool operator != (const txExpandedName& rhs) const
+ {
+ return ((mLocalName != rhs.mLocalName) ||
+ (mNamespaceID != rhs.mNamespaceID));
+ }
+
+ int32_t mNamespaceID;
+ nsCOMPtr<nsIAtom> mLocalName;
+};
+
+#endif
diff --git a/dom/xslt/base/txExpandedNameMap.cpp b/dom/xslt/base/txExpandedNameMap.cpp
new file mode 100644
index 000000000..b033d6155
--- /dev/null
+++ b/dom/xslt/base/txExpandedNameMap.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "txExpandedNameMap.h"
+#include "txCore.h"
+
+class txMapItemComparator
+{
+ public:
+ bool Equals(const txExpandedNameMap_base::MapItem& aItem,
+ const txExpandedName& aKey) const {
+ return aItem.mNamespaceID == aKey.mNamespaceID &&
+ aItem.mLocalName == aKey.mLocalName;
+ }
+};
+
+/**
+ * Adds an item, if an item with this key already exists an error is
+ * returned
+ * @param aKey key for item to add
+ * @param aValue value of item to add
+ * @return errorcode
+ */
+nsresult txExpandedNameMap_base::addItem(const txExpandedName& aKey,
+ void* aValue)
+{
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ return NS_ERROR_XSLT_ALREADY_SET;
+ }
+
+ MapItem* item = mItems.AppendElement();
+ NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
+
+ item->mNamespaceID = aKey.mNamespaceID;
+ item->mLocalName = aKey.mLocalName;
+ item->mValue = aValue;
+
+ return NS_OK;
+}
+
+/**
+ * Sets an item, if an item with this key already exists it is overwritten
+ * with the new value
+ * @param aKey key for item to set
+ * @param aValue value of item to set
+ * @return errorcode
+ */
+nsresult txExpandedNameMap_base::setItem(const txExpandedName& aKey,
+ void* aValue,
+ void** aOldValue)
+{
+ *aOldValue = nullptr;
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ *aOldValue = mItems[pos].mValue;
+ mItems[pos].mValue = aValue;
+ return NS_OK;
+ }
+
+ MapItem* item = mItems.AppendElement();
+ NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
+
+ item->mNamespaceID = aKey.mNamespaceID;
+ item->mLocalName = aKey.mLocalName;
+ item->mValue = aValue;
+
+ return NS_OK;
+}
+
+/**
+ * Gets an item
+ * @param aKey key for item to get
+ * @return item with specified key, or null if no such item exists
+ */
+void* txExpandedNameMap_base::getItem(const txExpandedName& aKey) const
+{
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ return mItems[pos].mValue;
+ }
+
+ return nullptr;
+}
+
+/**
+ * Removes an item, deleting it if the map owns the values
+ * @param aKey key for item to remove
+ * @return item with specified key, or null if it has been deleted
+ * or no such item exists
+ */
+void* txExpandedNameMap_base::removeItem(const txExpandedName& aKey)
+{
+ void* value = nullptr;
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ value = mItems[pos].mValue;
+ mItems.RemoveElementAt(pos);
+ }
+
+ return value;
+}
diff --git a/dom/xslt/base/txExpandedNameMap.h b/dom/xslt/base/txExpandedNameMap.h
new file mode 100644
index 000000000..de0861427
--- /dev/null
+++ b/dom/xslt/base/txExpandedNameMap.h
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TRANSFRMX_EXPANDEDNAMEMAP_H
+#define TRANSFRMX_EXPANDEDNAMEMAP_H
+
+#include "nsAutoPtr.h"
+#include "nsError.h"
+#include "txExpandedName.h"
+#include "nsTArray.h"
+
+class txExpandedNameMap_base {
+protected:
+ /**
+ * Adds an item, if an item with this key already exists an error is
+ * returned
+ * @param aKey key for item to add
+ * @param aValue value of item to add
+ * @return errorcode
+ */
+ nsresult addItem(const txExpandedName& aKey, void* aValue);
+
+ /**
+ * Sets an item, if an item with this key already exists it is overwritten
+ * with the new value
+ * @param aKey key for item to set
+ * @param aValue value of item to set
+ * @return errorcode
+ */
+ nsresult setItem(const txExpandedName& aKey, void* aValue,
+ void** aOldValue);
+
+ /**
+ * Gets an item
+ * @param aKey key for item to get
+ * @return item with specified key, or null if no such item exists
+ */
+ void* getItem(const txExpandedName& aKey) const;
+
+ /**
+ * Removes an item, deleting it if the map owns the values
+ * @param aKey key for item to remove
+ * @return item with specified key, or null if it has been deleted
+ * or no such item exists
+ */
+ void* removeItem(const txExpandedName& aKey);
+
+ /**
+ * Clears the items
+ */
+ void clearItems()
+ {
+ mItems.Clear();
+ }
+
+ class iterator_base {
+ public:
+ explicit iterator_base(txExpandedNameMap_base& aMap)
+ : mMap(aMap),
+ mCurrentPos(uint32_t(-1))
+ {
+ }
+
+ bool next()
+ {
+ return ++mCurrentPos < mMap.mItems.Length();
+ }
+
+ const txExpandedName key()
+ {
+ NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
+ "invalid position in txExpandedNameMap::iterator");
+ return txExpandedName(mMap.mItems[mCurrentPos].mNamespaceID,
+ mMap.mItems[mCurrentPos].mLocalName);
+ }
+
+ protected:
+ void* itemValue()
+ {
+ NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
+ "invalid position in txExpandedNameMap::iterator");
+ return mMap.mItems[mCurrentPos].mValue;
+ }
+
+ private:
+ txExpandedNameMap_base& mMap;
+ uint32_t mCurrentPos;
+ };
+
+ friend class iterator_base;
+
+ friend class txMapItemComparator;
+ struct MapItem {
+ int32_t mNamespaceID;
+ nsCOMPtr<nsIAtom> mLocalName;
+ void* mValue;
+ };
+
+ nsTArray<MapItem> mItems;
+};
+
+template<class E>
+class txExpandedNameMap : public txExpandedNameMap_base
+{
+public:
+ nsresult add(const txExpandedName& aKey, E* aValue)
+ {
+ return addItem(aKey, (void*)aValue);
+ }
+
+ nsresult set(const txExpandedName& aKey, E* aValue)
+ {
+ void* oldValue;
+ return setItem(aKey, (void*)aValue, &oldValue);
+ }
+
+ E* get(const txExpandedName& aKey) const
+ {
+ return (E*)getItem(aKey);
+ }
+
+ E* remove(const txExpandedName& aKey)
+ {
+ return (E*)removeItem(aKey);
+ }
+
+ void clear()
+ {
+ clearItems();
+ }
+
+ class iterator : public iterator_base
+ {
+ public:
+ explicit iterator(txExpandedNameMap& aMap)
+ : iterator_base(aMap)
+ {
+ }
+
+ E* value()
+ {
+ return (E*)itemValue();
+ }
+ };
+};
+
+template<class E>
+class txOwningExpandedNameMap : public txExpandedNameMap_base
+{
+public:
+ ~txOwningExpandedNameMap()
+ {
+ clear();
+ }
+
+ nsresult add(const txExpandedName& aKey, E* aValue)
+ {
+ return addItem(aKey, (void*)aValue);
+ }
+
+ nsresult set(const txExpandedName& aKey, E* aValue)
+ {
+ nsAutoPtr<E> oldValue;
+ return setItem(aKey, (void*)aValue, getter_Transfers(oldValue));
+ }
+
+ E* get(const txExpandedName& aKey) const
+ {
+ return (E*)getItem(aKey);
+ }
+
+ void remove(const txExpandedName& aKey)
+ {
+ delete (E*)removeItem(aKey);
+ }
+
+ void clear()
+ {
+ uint32_t i, len = mItems.Length();
+ for (i = 0; i < len; ++i) {
+ delete (E*)mItems[i].mValue;
+ }
+ clearItems();
+ }
+
+ class iterator : public iterator_base
+ {
+ public:
+ explicit iterator(txOwningExpandedNameMap& aMap)
+ : iterator_base(aMap)
+ {
+ }
+
+ E* value()
+ {
+ return (E*)itemValue();
+ }
+ };
+};
+
+#endif //TRANSFRMX_EXPANDEDNAMEMAP_H
diff --git a/dom/xslt/base/txList.cpp b/dom/xslt/base/txList.cpp
new file mode 100644
index 000000000..fa4952ad9
--- /dev/null
+++ b/dom/xslt/base/txList.cpp
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "txList.h"
+
+ //----------------------------/
+ //- Implementation of txList -/
+//----------------------------/
+
+/**
+ * Default constructor for a txList;
+**/
+
+txList::txList() {
+ firstItem = 0;
+ lastItem = 0;
+ itemCount = 0;
+} //-- txList;
+
+/**
+ * txList destructor, cleans up ListItems, but will not delete the Object
+ * references
+*/
+txList::~txList() {
+ clear();
+} //-- ~txList
+
+nsresult txList::add(void* objPtr)
+{
+ return insertBefore(objPtr, 0);
+} //-- add
+
+/**
+ * Returns the number of items in this txList
+**/
+int32_t List::getLength() {
+ return itemCount;
+} //-- getLength
+
+
+/**
+ * Inserts the given Object pointer as the item just after refItem.
+ * If refItem is a null pointer the Object will be inserted at the
+ * beginning of the txList (ie, insert after nothing).
+ * This method assumes refItem is a member of this list, and since this
+ * is a private method, I feel that's a valid assumption
+**/
+nsresult txList::insertAfter(void* objPtr, ListItem* refItem)
+{
+ //-- if refItem == null insert at front
+ if (!refItem)
+ return insertBefore(objPtr, firstItem);
+ return insertBefore(objPtr, refItem->nextItem);
+} //-- insertAfter
+
+/**
+ * Inserts the given Object pointer as the item just before refItem.
+ * If refItem is a null pointer the Object will be inserted at the
+ * end of the txList (ie, insert before nothing).
+ * This method assumes refItem is a member of this list, and since this
+ * is a private method, I feel that's a valid assumption
+**/
+nsresult txList::insertBefore(void* objPtr, ListItem* refItem)
+{
+ ListItem* item = new ListItem;
+ item->objPtr = objPtr;
+ item->nextItem = 0;
+ item->prevItem = 0;
+
+ //-- if refItem == null insert at end
+ if (!refItem) {
+ //-- add to back of list
+ if (lastItem) {
+ lastItem->nextItem = item;
+ item->prevItem = lastItem;
+ }
+ lastItem = item;
+ if (!firstItem)
+ firstItem = item;
+ }
+ else {
+ //-- insert before given item
+ item->nextItem = refItem;
+ item->prevItem = refItem->prevItem;
+ refItem->prevItem = item;
+
+ if (item->prevItem)
+ item->prevItem->nextItem = item;
+ else
+ firstItem = item;
+ }
+
+ // increase the item count
+ ++itemCount;
+
+ return NS_OK;
+} //-- insertBefore
+
+txList::ListItem* txList::remove(ListItem* item) {
+
+ if (!item)
+ return item;
+
+ //-- adjust the previous item's next pointer
+ if (item->prevItem) {
+ item->prevItem->nextItem = item->nextItem;
+ }
+ //-- adjust the next item's previous pointer
+ if (item->nextItem) {
+ item->nextItem->prevItem = item->prevItem;
+ }
+
+ //-- adjust first and last items
+ if (item == firstItem)
+ firstItem = item->nextItem;
+ if (item == lastItem)
+ lastItem = item->prevItem;
+
+ //-- decrease Item count
+ --itemCount;
+ return item;
+} //-- remove
+
+void txList::clear()
+{
+ ListItem* item = firstItem;
+ while (item) {
+ ListItem* tItem = item;
+ item = item->nextItem;
+ delete tItem;
+ }
+ firstItem = 0;
+ lastItem = 0;
+ itemCount = 0;
+}
+
+ //------------------------------------/
+ //- Implementation of txListIterator -/
+//------------------------------------/
+
+
+/**
+ * Creates a new txListIterator for the given txList
+ * @param list, the txList to create an Iterator for
+**/
+txListIterator::txListIterator(txList* list) {
+ this->list = list;
+ currentItem = 0;
+ atEndOfList = false;
+} //-- txListIterator
+
+/**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the next item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+**/
+nsresult txListIterator::addAfter(void* objPtr)
+{
+ if (currentItem || !atEndOfList)
+ return list->insertAfter(objPtr, currentItem);
+ return list->insertBefore(objPtr, 0);
+
+} //-- addAfter
+
+/**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the previous item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+**/
+nsresult txListIterator::addBefore(void* objPtr)
+{
+ if (currentItem || atEndOfList)
+ return list->insertBefore(objPtr, currentItem);
+ return list->insertAfter(objPtr, 0);
+
+} //-- addBefore
+
+/**
+ * Returns true if a successful call to the next() method can be made
+ * @return true if a successful call to the next() method can be made,
+ * otherwise false
+**/
+bool txListIterator::hasNext() {
+ bool hasNext = false;
+ if (currentItem)
+ hasNext = (currentItem->nextItem != 0);
+ else if (!atEndOfList)
+ hasNext = (list->firstItem != 0);
+
+ return hasNext;
+} //-- hasNext
+
+/**
+ * Returns the next Object pointer in the list
+**/
+void* txListIterator::next() {
+
+ void* obj = 0;
+ if (currentItem)
+ currentItem = currentItem->nextItem;
+ else if (!atEndOfList)
+ currentItem = list->firstItem;
+
+ if (currentItem)
+ obj = currentItem->objPtr;
+ else
+ atEndOfList = true;
+
+ return obj;
+} //-- next
+
+/**
+ * Returns the previous Object in the list
+**/
+void* txListIterator::previous() {
+
+ void* obj = 0;
+
+ if (currentItem)
+ currentItem = currentItem->prevItem;
+ else if (atEndOfList)
+ currentItem = list->lastItem;
+
+ if (currentItem)
+ obj = currentItem->objPtr;
+
+ atEndOfList = false;
+
+ return obj;
+} //-- previous
+
+/**
+ * Returns the current Object
+**/
+void* txListIterator::current() {
+
+ if (currentItem)
+ return currentItem->objPtr;
+
+ return 0;
+} //-- current
+
+/**
+ * Removes the Object last returned by the next() or previous() methods;
+ * @return the removed Object pointer
+**/
+void* txListIterator::remove() {
+
+ void* obj = 0;
+ if (currentItem) {
+ obj = currentItem->objPtr;
+ txList::ListItem* item = currentItem;
+ previous(); //-- make previous item the current item
+ list->remove(item);
+ delete item;
+ }
+ return obj;
+} //-- remove
+
+/**
+ * Resets the current location within the txList to the beginning of the txList
+**/
+void txListIterator::reset() {
+ atEndOfList = false;
+ currentItem = 0;
+} //-- reset
+
+/**
+ * Move the iterator to right after the last element
+**/
+void txListIterator::resetToEnd() {
+ atEndOfList = true;
+ currentItem = 0;
+} //-- moveToEnd
diff --git a/dom/xslt/base/txList.h b/dom/xslt/base/txList.h
new file mode 100644
index 000000000..180bab1af
--- /dev/null
+++ b/dom/xslt/base/txList.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TRANSFRMX_LIST_H
+#define TRANSFRMX_LIST_H
+
+#include "txCore.h"
+
+class txListIterator;
+
+/**
+ * Represents an ordered list of Object pointers. Modeled after a Java 2 List.
+**/
+class txList : public txObject {
+
+friend class txListIterator;
+
+public:
+
+ /**
+ * Creates an empty txList
+ **/
+ txList();
+
+ /**
+ * txList destructor, object references will not be deleted.
+ **/
+ ~txList();
+
+ /**
+ * Returns the number of items in this txList
+ **/
+ int32_t getLength();
+
+ /**
+ * Returns true if there are no items in this txList
+ */
+ inline bool isEmpty()
+ {
+ return itemCount == 0;
+ }
+
+ /**
+ * Adds the given Object to the list
+ **/
+ nsresult add(void* objPtr);
+
+ /*
+ * Removes all the objects from the list
+ */
+ void clear();
+
+protected:
+
+ struct ListItem {
+ ListItem* nextItem;
+ ListItem* prevItem;
+ void* objPtr;
+ };
+
+ /**
+ * Removes the given ListItem pointer from the list
+ **/
+ ListItem* remove(ListItem* sItem);
+
+private:
+ txList(const txList& aOther); // not implemented
+
+ ListItem* firstItem;
+ ListItem* lastItem;
+ int32_t itemCount;
+
+ nsresult insertAfter(void* objPtr, ListItem* sItem);
+ nsresult insertBefore(void* objPtr, ListItem* sItem);
+};
+
+
+
+/**
+ * An Iterator for the txList Class
+**/
+class txListIterator {
+
+public:
+ /**
+ * Creates a new txListIterator for the given txList
+ * @param list, the txList to create an Iterator for
+ **/
+ explicit txListIterator(txList* list);
+
+ /**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the next item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+ nsresult addAfter(void* objPtr);
+
+ /**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the previous item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+ nsresult addBefore(void* objPtr);
+
+ /**
+ * Returns true if a successful call to the next() method can be made
+ * @return true if a successful call to the next() method can be made,
+ * otherwise false
+ **/
+ bool hasNext();
+
+ /**
+ * Returns the next Object pointer from the list
+ **/
+ void* next();
+
+ /**
+ * Returns the previous Object pointer from the list
+ **/
+ void* previous();
+
+ /**
+ * Returns the current Object
+ **/
+ void* current();
+
+ /**
+ * Removes the Object last returned by the next() or previous() methods;
+ * @return the removed Object pointer
+ **/
+ void* remove();
+
+ /**
+ * Resets the current location within the txList to the beginning of the txList
+ **/
+ void reset();
+
+ /**
+ * Resets the current location within the txList to the end of the txList
+ **/
+ void resetToEnd();
+
+private:
+
+ //-- points to the current list item
+ txList::ListItem* currentItem;
+
+ //-- points to the list to iterator over
+ txList* list;
+
+ //-- we've moved off the end of the list
+ bool atEndOfList;
+};
+
+typedef txList List;
+
+#endif
diff --git a/dom/xslt/base/txLog.h b/dom/xslt/base/txLog.h
new file mode 100644
index 000000000..0387c9d60
--- /dev/null
+++ b/dom/xslt/base/txLog.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef txLog_h__
+#define txLog_h__
+
+#include "mozilla/Logging.h"
+
+class txLog
+{
+public:
+ static mozilla::LazyLogModule xpath;
+ static mozilla::LazyLogModule xslt;
+};
+
+#define TX_LG_IMPL \
+ mozilla::LazyLogModule txLog::xpath("xpath"); \
+ mozilla::LazyLogModule txLog::xslt("xslt");
+
+#define TX_LG_CREATE
+
+#endif
diff --git a/dom/xslt/base/txNamespaceMap.cpp b/dom/xslt/base/txNamespaceMap.cpp
new file mode 100644
index 000000000..cb6c4b164
--- /dev/null
+++ b/dom/xslt/base/txNamespaceMap.cpp
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "txNamespaceMap.h"
+#include "nsGkAtoms.h"
+#include "txXPathNode.h"
+
+txNamespaceMap::txNamespaceMap()
+{
+}
+
+txNamespaceMap::txNamespaceMap(const txNamespaceMap& aOther)
+ : mPrefixes(aOther.mPrefixes)
+{
+ mNamespaces = aOther.mNamespaces; //bah! I want a copy-constructor!
+}
+
+nsresult
+txNamespaceMap::mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI)
+{
+ nsIAtom* prefix = aPrefix == nsGkAtoms::_empty ? nullptr : aPrefix;
+
+ int32_t nsId;
+ if (prefix && aNamespaceURI.IsEmpty()) {
+ // Remove the mapping
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ mPrefixes.RemoveObjectAt(index);
+ mNamespaces.RemoveElementAt(index);
+ }
+
+ return NS_OK;
+ }
+
+ if (aNamespaceURI.IsEmpty()) {
+ // Set default to empty namespace
+ nsId = kNameSpaceID_None;
+ }
+ else {
+ nsId = txNamespaceManager::getNamespaceID(aNamespaceURI);
+ NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown, NS_ERROR_FAILURE);
+ }
+
+ // Check if the mapping already exists
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ mNamespaces.ElementAt(index) = nsId;
+
+ return NS_OK;
+ }
+
+ // New mapping
+ if (!mPrefixes.AppendObject(prefix)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (mNamespaces.AppendElement(nsId) == nullptr) {
+ mPrefixes.RemoveObjectAt(mPrefixes.Count() - 1);
+
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return NS_OK;
+}
+
+int32_t
+txNamespaceMap::lookupNamespace(nsIAtom* aPrefix)
+{
+ if (aPrefix == nsGkAtoms::xml) {
+ return kNameSpaceID_XML;
+ }
+
+ nsIAtom* prefix = aPrefix == nsGkAtoms::_empty ? 0 : aPrefix;
+
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ return mNamespaces.SafeElementAt(index, kNameSpaceID_Unknown);
+ }
+
+ if (!prefix) {
+ return kNameSpaceID_None;
+ }
+
+ return kNameSpaceID_Unknown;
+}
+
+int32_t
+txNamespaceMap::lookupNamespaceWithDefault(const nsAString& aPrefix)
+{
+ nsCOMPtr<nsIAtom> prefix = NS_Atomize(aPrefix);
+ if (prefix != nsGkAtoms::_poundDefault) {
+ return lookupNamespace(prefix);
+ }
+
+ return lookupNamespace(nullptr);
+}
diff --git a/dom/xslt/base/txNamespaceMap.h b/dom/xslt/base/txNamespaceMap.h
new file mode 100644
index 000000000..0e6be57c6
--- /dev/null
+++ b/dom/xslt/base/txNamespaceMap.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TRANSFRMX_TXNAMESPACEMAP_H
+#define TRANSFRMX_TXNAMESPACEMAP_H
+
+#include "nsIAtom.h"
+#include "nsCOMArray.h"
+#include "nsTArray.h"
+
+class txNamespaceMap
+{
+public:
+ txNamespaceMap();
+ txNamespaceMap(const txNamespaceMap& aOther);
+
+ nsrefcnt AddRef()
+ {
+ return ++mRefCnt;
+ }
+ nsrefcnt Release()
+ {
+ if (--mRefCnt == 0) {
+ mRefCnt = 1; //stabilize
+ delete this;
+ return 0;
+ }
+ return mRefCnt;
+ }
+
+ nsresult mapNamespace(nsIAtom* aPrefix, const nsAString& aNamespaceURI);
+ int32_t lookupNamespace(nsIAtom* aPrefix);
+ int32_t lookupNamespaceWithDefault(const nsAString& aPrefix);
+
+private:
+ nsAutoRefCnt mRefCnt;
+ nsCOMArray<nsIAtom> mPrefixes;
+ nsTArray<int32_t> mNamespaces;
+};
+
+#endif //TRANSFRMX_TXNAMESPACEMAP_H
diff --git a/dom/xslt/base/txOwningArray.h b/dom/xslt/base/txOwningArray.h
new file mode 100644
index 000000000..6ec7ebd22
--- /dev/null
+++ b/dom/xslt/base/txOwningArray.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef txOwningArray_h__
+#define txOwningArray_h__
+
+// Class acting like a nsTArray except that it deletes its objects
+// on destruction. It does not however delete its objects on operations
+// like RemoveElementsAt or on |array[i] = bar|.
+
+template<class E>
+class txOwningArray : public nsTArray<E*>
+{
+public:
+ typedef nsTArray<E*> base_type;
+ typedef typename base_type::elem_type elem_type;
+
+ ~txOwningArray()
+ {
+ elem_type* iter = base_type::Elements();
+ elem_type* end = iter + base_type::Length();
+ for (; iter < end; ++iter) {
+ delete *iter;
+ }
+ }
+
+};
+
+#endif // txOwningArray_h__
diff --git a/dom/xslt/base/txStack.h b/dom/xslt/base/txStack.h
new file mode 100644
index 000000000..53ce29862
--- /dev/null
+++ b/dom/xslt/base/txStack.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef txStack_h___
+#define txStack_h___
+
+#include "nsTArray.h"
+
+class txStack : private nsTArray<void*>
+{
+public:
+ /**
+ * Returns the specified object from the top of this stack,
+ * without removing it from the stack.
+ *
+ * @return a pointer to the object that is the top of this stack.
+ */
+ inline void* peek()
+ {
+ NS_ASSERTION(!isEmpty(), "peeking at empty stack");
+ return !isEmpty() ? ElementAt(Length() - 1) : nullptr;
+ }
+
+ /**
+ * Adds the specified object to the top of this stack.
+ *
+ * @param obj a pointer to the object that is to be added to the
+ * top of this stack.
+ */
+ inline nsresult push(void* aObject)
+ {
+ return AppendElement(aObject) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ /**
+ * Removes and returns the specified object from the top of this
+ * stack.
+ *
+ * @return a pointer to the object that was the top of this stack.
+ */
+ inline void* pop()
+ {
+ void* object = nullptr;
+ NS_ASSERTION(!isEmpty(), "popping from empty stack");
+ if (!isEmpty())
+ {
+ const uint32_t count = Length() - 1;
+ object = ElementAt(count);
+ RemoveElementAt(count);
+ }
+ return object;
+ }
+
+ /**
+ * Returns true if there are no objects in the stack.
+ *
+ * @return true if there are no objects in the stack.
+ */
+ inline bool isEmpty()
+ {
+ return IsEmpty();
+ }
+
+ /**
+ * Returns the number of elements in the Stack.
+ *
+ * @return the number of elements in the Stack.
+ */
+ inline int32_t size()
+ {
+ return Length();
+ }
+
+private:
+ friend class txStackIterator;
+};
+
+class txStackIterator
+{
+public:
+ /**
+ * Creates an iterator for the given stack.
+ *
+ * @param aStack the stack to create an iterator for.
+ */
+ inline
+ explicit txStackIterator(txStack* aStack) : mStack(aStack),
+ mPosition(0)
+ {
+ }
+
+ /**
+ * Returns true if there is more objects on the stack.
+ *
+ * @return .
+ */
+ inline bool hasNext()
+ {
+ return (mPosition < mStack->Length());
+ }
+
+ /**
+ * Returns the next object pointer from the stack.
+ *
+ * @return .
+ */
+ inline void* next()
+ {
+ if (mPosition == mStack->Length()) {
+ return nullptr;
+ }
+ return mStack->ElementAt(mPosition++);
+ }
+
+private:
+ txStack* mStack;
+ uint32_t mPosition;
+};
+
+#endif /* txStack_h___ */
diff --git a/dom/xslt/base/txStringUtils.h b/dom/xslt/base/txStringUtils.h
new file mode 100644
index 000000000..6f45fe661
--- /dev/null
+++ b/dom/xslt/base/txStringUtils.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef txStringUtils_h__
+#define txStringUtils_h__
+
+#include "nsAString.h"
+#include "nsIAtom.h"
+#include "nsUnicharUtils.h"
+#include "nsContentUtils.h" // For ASCIIToLower().
+
+typedef nsCaseInsensitiveStringComparator txCaseInsensitiveStringComparator;
+
+/**
+ * Check equality between a string and an atom containing ASCII.
+ */
+inline bool
+TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom)
+{
+ return aAtom->Equals(aString);
+}
+
+inline already_AddRefed<nsIAtom>
+TX_ToLowerCaseAtom(nsIAtom* aAtom)
+{
+ nsAutoString str;
+ aAtom->ToString(str);
+ nsContentUtils::ASCIIToLower(str);
+ return NS_Atomize(str);
+}
+
+#endif // txStringUtils_h__
diff --git a/dom/xslt/base/txURIUtils.cpp b/dom/xslt/base/txURIUtils.cpp
new file mode 100644
index 000000000..3f3556f80
--- /dev/null
+++ b/dom/xslt/base/txURIUtils.cpp
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "txURIUtils.h"
+#include "nsNetUtil.h"
+#include "nsIDocument.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsIPrincipal.h"
+#include "mozilla/LoadInfo.h"
+
+using mozilla::net::LoadInfo;
+
+/**
+ * URIUtils
+ * A set of utilities for handling URIs
+**/
+
+/**
+ * Resolves the given href argument, using the given documentBase
+ * if necessary.
+ * The new resolved href will be appended to the given dest String
+**/
+void URIUtils::resolveHref(const nsAString& href, const nsAString& base,
+ nsAString& dest) {
+ if (base.IsEmpty()) {
+ dest.Append(href);
+ return;
+ }
+ if (href.IsEmpty()) {
+ dest.Append(base);
+ return;
+ }
+ nsCOMPtr<nsIURI> pURL;
+ nsAutoString resultHref;
+ nsresult result = NS_NewURI(getter_AddRefs(pURL), base);
+ if (NS_SUCCEEDED(result)) {
+ NS_MakeAbsoluteURI(resultHref, href, pURL);
+ dest.Append(resultHref);
+ }
+} //-- resolveHref
+
+// static
+void
+URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsINode *aSourceNode)
+{
+ nsCOMPtr<nsIDocument> sourceDoc = aSourceNode->OwnerDoc();
+ nsIPrincipal* sourcePrincipal = sourceDoc->NodePrincipal();
+
+ // Copy the channel and loadgroup from the source document.
+ nsCOMPtr<nsILoadGroup> loadGroup = sourceDoc->GetDocumentLoadGroup();
+ nsCOMPtr<nsIChannel> channel = sourceDoc->GetChannel();
+ if (!channel) {
+ // Need to synthesize one
+ nsresult rv = NS_NewChannel(getter_AddRefs(channel),
+ sourceDoc->GetDocumentURI(),
+ sourceDoc,
+ nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
+ nsIContentPolicy::TYPE_OTHER,
+ loadGroup,
+ nullptr, // aCallbacks
+ nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
+
+ if (NS_FAILED(rv)) {
+ return;
+ }
+ }
+
+ aNewDoc->Reset(channel, loadGroup);
+ aNewDoc->SetPrincipal(sourcePrincipal);
+ aNewDoc->SetBaseURI(sourceDoc->GetDocBaseURI());
+
+ // Copy charset
+ aNewDoc->SetDocumentCharacterSetSource(
+ sourceDoc->GetDocumentCharacterSetSource());
+ aNewDoc->SetDocumentCharacterSet(sourceDoc->GetDocumentCharacterSet());
+}
diff --git a/dom/xslt/base/txURIUtils.h b/dom/xslt/base/txURIUtils.h
new file mode 100644
index 000000000..ad182a00a
--- /dev/null
+++ b/dom/xslt/base/txURIUtils.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TRANSFRMX_URIUTILS_H
+#define TRANSFRMX_URIUTILS_H
+
+#include "txCore.h"
+
+class nsIDocument;
+class nsINode;
+
+/**
+ * A utility class for URI handling
+ * Not yet finished, only handles file URI at this point
+**/
+
+class URIUtils {
+public:
+
+ /**
+ * Reset the given document with the document of the source node
+ */
+ static void ResetWithSource(nsIDocument *aNewDoc, nsINode *aSourceNode);
+
+ /**
+ * Resolves the given href argument, using the given documentBase
+ * if necessary.
+ * The new resolved href will be appended to the given dest String
+ **/
+ static void resolveHref(const nsAString& href, const nsAString& base,
+ nsAString& dest);
+}; //-- URIUtils
+
+/* */
+#endif