michael@0: /* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim:set ts=4 sw=4 sts=4: */ 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: #include "nsHashPropertyBag.h" michael@0: #include "nsArray.h" michael@0: #include "nsArrayEnumerator.h" michael@0: #include "nsIVariant.h" michael@0: #include "nsIProperty.h" michael@0: #include "nsVariant.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: nsresult michael@0: NS_NewHashPropertyBag(nsIWritablePropertyBag* *_retval) michael@0: { michael@0: nsRefPtr hpb = new nsHashPropertyBag(); michael@0: hpb.forget(_retval); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* michael@0: * nsHashPropertyBag impl michael@0: */ michael@0: michael@0: NS_IMPL_ADDREF(nsHashPropertyBag) michael@0: NS_IMPL_RELEASE(nsHashPropertyBag) michael@0: NS_INTERFACE_MAP_BEGIN(nsHashPropertyBag) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIPropertyBag, nsIWritablePropertyBag) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWritablePropertyBag) michael@0: NS_INTERFACE_MAP_ENTRY(nsIPropertyBag2) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag2) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::HasKey(const nsAString& name, bool *aResult) michael@0: { michael@0: *aResult = mPropertyHash.Get(name, nullptr); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::Get(const nsAString& name, nsIVariant* *_retval) michael@0: { michael@0: if (!mPropertyHash.Get(name, _retval)) michael@0: *_retval = nullptr; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetProperty(const nsAString& name, nsIVariant* *_retval) michael@0: { michael@0: bool isFound = mPropertyHash.Get(name, _retval); michael@0: if (!isFound) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::SetProperty(const nsAString& name, nsIVariant *value) michael@0: { michael@0: if (NS_WARN_IF(!value)) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: mPropertyHash.Put(name, value); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::DeleteProperty(const nsAString& name) michael@0: { michael@0: // is it too much to ask for ns*Hashtable to return michael@0: // a boolean indicating whether RemoveEntry succeeded michael@0: // or not?!?! michael@0: bool isFound = mPropertyHash.Get(name, nullptr); michael@0: if (!isFound) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // then from the hash michael@0: mPropertyHash.Remove(name); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: // michael@0: // nsSimpleProperty class and impl; used for GetEnumerator michael@0: // michael@0: michael@0: class nsSimpleProperty MOZ_FINAL : public nsIProperty { michael@0: public: michael@0: nsSimpleProperty(const nsAString& aName, nsIVariant* aValue) michael@0: : mName(aName), mValue(aValue) michael@0: { michael@0: } michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIPROPERTY michael@0: protected: michael@0: nsString mName; michael@0: nsCOMPtr mValue; michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsSimpleProperty, nsIProperty) michael@0: michael@0: NS_IMETHODIMP michael@0: nsSimpleProperty::GetName(nsAString& aName) michael@0: { michael@0: aName.Assign(mName); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSimpleProperty::GetValue(nsIVariant* *aValue) michael@0: { michael@0: NS_IF_ADDREF(*aValue = mValue); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // end nsSimpleProperty michael@0: michael@0: static PLDHashOperator michael@0: PropertyHashToArrayFunc (const nsAString &aKey, michael@0: nsIVariant* aData, michael@0: void *userArg) michael@0: { michael@0: nsIMutableArray *propertyArray = michael@0: static_cast(userArg); michael@0: nsSimpleProperty *sprop = new nsSimpleProperty(aKey, aData); michael@0: propertyArray->AppendElement(sprop, false); michael@0: return PL_DHASH_NEXT; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetEnumerator(nsISimpleEnumerator* *_retval) michael@0: { michael@0: nsCOMPtr propertyArray = nsArray::Create(); michael@0: if (!propertyArray) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: mPropertyHash.EnumerateRead(PropertyHashToArrayFunc, propertyArray.get()); michael@0: michael@0: return NS_NewArrayEnumerator(_retval, propertyArray); michael@0: } michael@0: michael@0: #define IMPL_GETSETPROPERTY_AS(Name, Type) \ michael@0: NS_IMETHODIMP \ michael@0: nsHashPropertyBag::GetPropertyAs ## Name (const nsAString & prop, Type *_retval) \ michael@0: { \ michael@0: nsIVariant* v = mPropertyHash.GetWeak(prop); \ michael@0: if (!v) \ michael@0: return NS_ERROR_NOT_AVAILABLE; \ michael@0: return v->GetAs ## Name(_retval); \ michael@0: } \ michael@0: \ michael@0: NS_IMETHODIMP \ michael@0: nsHashPropertyBag::SetPropertyAs ## Name (const nsAString & prop, Type value) \ michael@0: { \ michael@0: nsCOMPtr var = new nsVariant(); \ michael@0: var->SetAs ## Name(value); \ michael@0: return SetProperty(prop, var); \ michael@0: } michael@0: michael@0: IMPL_GETSETPROPERTY_AS(Int32, int32_t) michael@0: IMPL_GETSETPROPERTY_AS(Uint32, uint32_t) michael@0: IMPL_GETSETPROPERTY_AS(Int64, int64_t) michael@0: IMPL_GETSETPROPERTY_AS(Uint64, uint64_t) michael@0: IMPL_GETSETPROPERTY_AS(Double, double) michael@0: IMPL_GETSETPROPERTY_AS(Bool, bool) michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetPropertyAsAString(const nsAString & prop, nsAString & _retval) michael@0: { michael@0: nsIVariant* v = mPropertyHash.GetWeak(prop); michael@0: if (!v) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: return v->GetAsAString(_retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetPropertyAsACString(const nsAString & prop, nsACString & _retval) michael@0: { michael@0: nsIVariant* v = mPropertyHash.GetWeak(prop); michael@0: if (!v) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: return v->GetAsACString(_retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetPropertyAsAUTF8String(const nsAString & prop, nsACString & _retval) michael@0: { michael@0: nsIVariant* v = mPropertyHash.GetWeak(prop); michael@0: if (!v) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: return v->GetAsAUTF8String(_retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::GetPropertyAsInterface(const nsAString & prop, michael@0: const nsIID & aIID, michael@0: void** _retval) michael@0: { michael@0: nsIVariant* v = mPropertyHash.GetWeak(prop); michael@0: if (!v) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: nsCOMPtr val; michael@0: nsresult rv = v->GetAsISupports(getter_AddRefs(val)); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: if (!val) { michael@0: // We have a value, but it's null michael@0: *_retval = nullptr; michael@0: return NS_OK; michael@0: } michael@0: return val->QueryInterface(aIID, _retval); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::SetPropertyAsAString(const nsAString & prop, const nsAString & value) michael@0: { michael@0: nsCOMPtr var = new nsVariant(); michael@0: var->SetAsAString(value); michael@0: return SetProperty(prop, var); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::SetPropertyAsACString(const nsAString & prop, const nsACString & value) michael@0: { michael@0: nsCOMPtr var = new nsVariant(); michael@0: var->SetAsACString(value); michael@0: return SetProperty(prop, var); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::SetPropertyAsAUTF8String(const nsAString & prop, const nsACString & value) michael@0: { michael@0: nsCOMPtr var = new nsVariant(); michael@0: var->SetAsAUTF8String(value); michael@0: return SetProperty(prop, var); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHashPropertyBag::SetPropertyAsInterface(const nsAString & prop, nsISupports* value) michael@0: { michael@0: nsCOMPtr var = new nsVariant(); michael@0: var->SetAsISupports(value); michael@0: return SetProperty(prop, var); michael@0: } michael@0: