|
1 /* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* vim:set ts=4 sw=4 sts=4: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "nsHashPropertyBag.h" |
|
8 #include "nsArray.h" |
|
9 #include "nsArrayEnumerator.h" |
|
10 #include "nsIVariant.h" |
|
11 #include "nsIProperty.h" |
|
12 #include "nsVariant.h" |
|
13 #include "mozilla/Attributes.h" |
|
14 |
|
15 nsresult |
|
16 NS_NewHashPropertyBag(nsIWritablePropertyBag* *_retval) |
|
17 { |
|
18 nsRefPtr<nsHashPropertyBag> hpb = new nsHashPropertyBag(); |
|
19 hpb.forget(_retval); |
|
20 return NS_OK; |
|
21 } |
|
22 |
|
23 /* |
|
24 * nsHashPropertyBag impl |
|
25 */ |
|
26 |
|
27 NS_IMPL_ADDREF(nsHashPropertyBag) |
|
28 NS_IMPL_RELEASE(nsHashPropertyBag) |
|
29 NS_INTERFACE_MAP_BEGIN(nsHashPropertyBag) |
|
30 NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag) |
|
31 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIPropertyBag, nsIWritablePropertyBag) |
|
32 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWritablePropertyBag) |
|
33 NS_INTERFACE_MAP_ENTRY(nsIPropertyBag2) |
|
34 NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag2) |
|
35 NS_INTERFACE_MAP_END |
|
36 |
|
37 NS_IMETHODIMP |
|
38 nsHashPropertyBag::HasKey(const nsAString& name, bool *aResult) |
|
39 { |
|
40 *aResult = mPropertyHash.Get(name, nullptr); |
|
41 |
|
42 return NS_OK; |
|
43 } |
|
44 |
|
45 NS_IMETHODIMP |
|
46 nsHashPropertyBag::Get(const nsAString& name, nsIVariant* *_retval) |
|
47 { |
|
48 if (!mPropertyHash.Get(name, _retval)) |
|
49 *_retval = nullptr; |
|
50 |
|
51 return NS_OK; |
|
52 } |
|
53 |
|
54 NS_IMETHODIMP |
|
55 nsHashPropertyBag::GetProperty(const nsAString& name, nsIVariant* *_retval) |
|
56 { |
|
57 bool isFound = mPropertyHash.Get(name, _retval); |
|
58 if (!isFound) |
|
59 return NS_ERROR_FAILURE; |
|
60 |
|
61 return NS_OK; |
|
62 } |
|
63 |
|
64 NS_IMETHODIMP |
|
65 nsHashPropertyBag::SetProperty(const nsAString& name, nsIVariant *value) |
|
66 { |
|
67 if (NS_WARN_IF(!value)) |
|
68 return NS_ERROR_INVALID_ARG; |
|
69 |
|
70 mPropertyHash.Put(name, value); |
|
71 |
|
72 return NS_OK; |
|
73 } |
|
74 |
|
75 NS_IMETHODIMP |
|
76 nsHashPropertyBag::DeleteProperty(const nsAString& name) |
|
77 { |
|
78 // is it too much to ask for ns*Hashtable to return |
|
79 // a boolean indicating whether RemoveEntry succeeded |
|
80 // or not?!?! |
|
81 bool isFound = mPropertyHash.Get(name, nullptr); |
|
82 if (!isFound) |
|
83 return NS_ERROR_FAILURE; |
|
84 |
|
85 // then from the hash |
|
86 mPropertyHash.Remove(name); |
|
87 |
|
88 return NS_OK; |
|
89 } |
|
90 |
|
91 |
|
92 // |
|
93 // nsSimpleProperty class and impl; used for GetEnumerator |
|
94 // |
|
95 |
|
96 class nsSimpleProperty MOZ_FINAL : public nsIProperty { |
|
97 public: |
|
98 nsSimpleProperty(const nsAString& aName, nsIVariant* aValue) |
|
99 : mName(aName), mValue(aValue) |
|
100 { |
|
101 } |
|
102 |
|
103 NS_DECL_ISUPPORTS |
|
104 NS_DECL_NSIPROPERTY |
|
105 protected: |
|
106 nsString mName; |
|
107 nsCOMPtr<nsIVariant> mValue; |
|
108 }; |
|
109 |
|
110 NS_IMPL_ISUPPORTS(nsSimpleProperty, nsIProperty) |
|
111 |
|
112 NS_IMETHODIMP |
|
113 nsSimpleProperty::GetName(nsAString& aName) |
|
114 { |
|
115 aName.Assign(mName); |
|
116 return NS_OK; |
|
117 } |
|
118 |
|
119 NS_IMETHODIMP |
|
120 nsSimpleProperty::GetValue(nsIVariant* *aValue) |
|
121 { |
|
122 NS_IF_ADDREF(*aValue = mValue); |
|
123 return NS_OK; |
|
124 } |
|
125 |
|
126 // end nsSimpleProperty |
|
127 |
|
128 static PLDHashOperator |
|
129 PropertyHashToArrayFunc (const nsAString &aKey, |
|
130 nsIVariant* aData, |
|
131 void *userArg) |
|
132 { |
|
133 nsIMutableArray *propertyArray = |
|
134 static_cast<nsIMutableArray *>(userArg); |
|
135 nsSimpleProperty *sprop = new nsSimpleProperty(aKey, aData); |
|
136 propertyArray->AppendElement(sprop, false); |
|
137 return PL_DHASH_NEXT; |
|
138 } |
|
139 |
|
140 |
|
141 NS_IMETHODIMP |
|
142 nsHashPropertyBag::GetEnumerator(nsISimpleEnumerator* *_retval) |
|
143 { |
|
144 nsCOMPtr<nsIMutableArray> propertyArray = nsArray::Create(); |
|
145 if (!propertyArray) |
|
146 return NS_ERROR_OUT_OF_MEMORY; |
|
147 |
|
148 mPropertyHash.EnumerateRead(PropertyHashToArrayFunc, propertyArray.get()); |
|
149 |
|
150 return NS_NewArrayEnumerator(_retval, propertyArray); |
|
151 } |
|
152 |
|
153 #define IMPL_GETSETPROPERTY_AS(Name, Type) \ |
|
154 NS_IMETHODIMP \ |
|
155 nsHashPropertyBag::GetPropertyAs ## Name (const nsAString & prop, Type *_retval) \ |
|
156 { \ |
|
157 nsIVariant* v = mPropertyHash.GetWeak(prop); \ |
|
158 if (!v) \ |
|
159 return NS_ERROR_NOT_AVAILABLE; \ |
|
160 return v->GetAs ## Name(_retval); \ |
|
161 } \ |
|
162 \ |
|
163 NS_IMETHODIMP \ |
|
164 nsHashPropertyBag::SetPropertyAs ## Name (const nsAString & prop, Type value) \ |
|
165 { \ |
|
166 nsCOMPtr<nsIWritableVariant> var = new nsVariant(); \ |
|
167 var->SetAs ## Name(value); \ |
|
168 return SetProperty(prop, var); \ |
|
169 } |
|
170 |
|
171 IMPL_GETSETPROPERTY_AS(Int32, int32_t) |
|
172 IMPL_GETSETPROPERTY_AS(Uint32, uint32_t) |
|
173 IMPL_GETSETPROPERTY_AS(Int64, int64_t) |
|
174 IMPL_GETSETPROPERTY_AS(Uint64, uint64_t) |
|
175 IMPL_GETSETPROPERTY_AS(Double, double) |
|
176 IMPL_GETSETPROPERTY_AS(Bool, bool) |
|
177 |
|
178 |
|
179 NS_IMETHODIMP |
|
180 nsHashPropertyBag::GetPropertyAsAString(const nsAString & prop, nsAString & _retval) |
|
181 { |
|
182 nsIVariant* v = mPropertyHash.GetWeak(prop); |
|
183 if (!v) |
|
184 return NS_ERROR_NOT_AVAILABLE; |
|
185 return v->GetAsAString(_retval); |
|
186 } |
|
187 |
|
188 NS_IMETHODIMP |
|
189 nsHashPropertyBag::GetPropertyAsACString(const nsAString & prop, nsACString & _retval) |
|
190 { |
|
191 nsIVariant* v = mPropertyHash.GetWeak(prop); |
|
192 if (!v) |
|
193 return NS_ERROR_NOT_AVAILABLE; |
|
194 return v->GetAsACString(_retval); |
|
195 } |
|
196 |
|
197 NS_IMETHODIMP |
|
198 nsHashPropertyBag::GetPropertyAsAUTF8String(const nsAString & prop, nsACString & _retval) |
|
199 { |
|
200 nsIVariant* v = mPropertyHash.GetWeak(prop); |
|
201 if (!v) |
|
202 return NS_ERROR_NOT_AVAILABLE; |
|
203 return v->GetAsAUTF8String(_retval); |
|
204 } |
|
205 |
|
206 NS_IMETHODIMP |
|
207 nsHashPropertyBag::GetPropertyAsInterface(const nsAString & prop, |
|
208 const nsIID & aIID, |
|
209 void** _retval) |
|
210 { |
|
211 nsIVariant* v = mPropertyHash.GetWeak(prop); |
|
212 if (!v) |
|
213 return NS_ERROR_NOT_AVAILABLE; |
|
214 nsCOMPtr<nsISupports> val; |
|
215 nsresult rv = v->GetAsISupports(getter_AddRefs(val)); |
|
216 if (NS_FAILED(rv)) |
|
217 return rv; |
|
218 if (!val) { |
|
219 // We have a value, but it's null |
|
220 *_retval = nullptr; |
|
221 return NS_OK; |
|
222 } |
|
223 return val->QueryInterface(aIID, _retval); |
|
224 } |
|
225 |
|
226 NS_IMETHODIMP |
|
227 nsHashPropertyBag::SetPropertyAsAString(const nsAString & prop, const nsAString & value) |
|
228 { |
|
229 nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
|
230 var->SetAsAString(value); |
|
231 return SetProperty(prop, var); |
|
232 } |
|
233 |
|
234 NS_IMETHODIMP |
|
235 nsHashPropertyBag::SetPropertyAsACString(const nsAString & prop, const nsACString & value) |
|
236 { |
|
237 nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
|
238 var->SetAsACString(value); |
|
239 return SetProperty(prop, var); |
|
240 } |
|
241 |
|
242 NS_IMETHODIMP |
|
243 nsHashPropertyBag::SetPropertyAsAUTF8String(const nsAString & prop, const nsACString & value) |
|
244 { |
|
245 nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
|
246 var->SetAsAUTF8String(value); |
|
247 return SetProperty(prop, var); |
|
248 } |
|
249 |
|
250 NS_IMETHODIMP |
|
251 nsHashPropertyBag::SetPropertyAsInterface(const nsAString & prop, nsISupports* value) |
|
252 { |
|
253 nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
|
254 var->SetAsISupports(value); |
|
255 return SetProperty(prop, var); |
|
256 } |
|
257 |