michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Class for representing MozMap arguments. This is an nsTHashtable michael@0: * under the hood, but we don't want to leak that implementation michael@0: * detail. michael@0: */ michael@0: michael@0: #ifndef mozilla_dom_MozMap_h michael@0: #define mozilla_dom_MozMap_h michael@0: michael@0: #include "nsTHashtable.h" michael@0: #include "nsHashKeys.h" michael@0: #include "nsStringGlue.h" michael@0: #include "nsTArray.h" michael@0: #include "mozilla/Move.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: namespace binding_detail { michael@0: template michael@0: class MozMapEntry : public nsStringHashKey michael@0: { michael@0: public: michael@0: MozMapEntry(const nsAString* aKeyTypePointer) michael@0: : nsStringHashKey(aKeyTypePointer) michael@0: { michael@0: } michael@0: michael@0: // Move constructor so we can do MozMaps of MozMaps. michael@0: MozMapEntry(MozMapEntry&& aOther) michael@0: : nsStringHashKey(aOther), michael@0: mData(Move(aOther.mData)) michael@0: { michael@0: } michael@0: michael@0: DataType mData; michael@0: }; michael@0: } // namespace binding_detail michael@0: michael@0: template michael@0: class MozMap : protected nsTHashtable> michael@0: { michael@0: public: michael@0: typedef typename binding_detail::MozMapEntry EntryType; michael@0: typedef nsTHashtable Base; michael@0: typedef MozMap SelfType; michael@0: michael@0: MozMap() michael@0: { michael@0: } michael@0: michael@0: // Move constructor so we can do MozMap of MozMap. michael@0: MozMap(SelfType&& aOther) : michael@0: Base(Move(aOther)) michael@0: { michael@0: } michael@0: michael@0: // The return value is only safe to use until an AddEntry call. michael@0: const DataType& Get(const nsAString& aKey) const michael@0: { michael@0: const EntryType* ent = this->GetEntry(aKey); michael@0: MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?"); michael@0: return ent->mData; michael@0: } michael@0: michael@0: // The return value is only safe to use until an AddEntry call. michael@0: const DataType* GetIfExists(const nsAString& aKey) const michael@0: { michael@0: const EntryType* ent = this->GetEntry(aKey); michael@0: if (!ent) { michael@0: return nullptr; michael@0: } michael@0: return &ent->mData; michael@0: } michael@0: michael@0: void GetKeys(nsTArray& aKeys) const { michael@0: // Sadly, EnumerateEntries is not a const method michael@0: const_cast(this)->EnumerateEntries(KeyEnumerator, &aKeys); michael@0: } michael@0: michael@0: // XXXbz we expose this generic enumerator for tracing. Otherwise we'd end up michael@0: // with a dependency on BindingUtils.h here for the SequenceTracer bits. michael@0: typedef PLDHashOperator (* Enumerator)(DataType* aValue, void* aClosure); michael@0: void EnumerateValues(Enumerator aEnumerator, void *aClosure) michael@0: { michael@0: ValueEnumClosure args = { aEnumerator, aClosure }; michael@0: this->EnumerateEntries(ValueEnumerator, &args); michael@0: } michael@0: michael@0: DataType* AddEntry(const nsAString& aKey) NS_WARN_UNUSED_RESULT michael@0: { michael@0: // XXXbz can't just use fallible_t() because our superclass has a michael@0: // private typedef by that name. michael@0: EntryType* ent = this->PutEntry(aKey, mozilla::fallible_t()); michael@0: if (!ent) { michael@0: return nullptr; michael@0: } michael@0: return &ent->mData; michael@0: } michael@0: michael@0: private: michael@0: static PLDHashOperator michael@0: KeyEnumerator(EntryType* aEntry, void* aClosure) michael@0: { michael@0: nsTArray& keys = *static_cast*>(aClosure); michael@0: keys.AppendElement(aEntry->GetKey()); michael@0: return PL_DHASH_NEXT; michael@0: } michael@0: michael@0: struct ValueEnumClosure { michael@0: Enumerator mEnumerator; michael@0: void* mClosure; michael@0: }; michael@0: michael@0: static PLDHashOperator michael@0: ValueEnumerator(EntryType* aEntry, void* aClosure) michael@0: { michael@0: ValueEnumClosure* enumClosure = static_cast(aClosure); michael@0: return enumClosure->mEnumerator(&aEntry->mData, enumClosure->mClosure); michael@0: } michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_dom_MozMap_h