Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "nsString.h"
8 : #include "nsReadableUtils.h"
9 : #include "nsTArray.h"
10 : #include "nsISimpleEnumerator.h"
11 : #include "nsXPCOM.h"
12 : #include "nsSupportsPrimitives.h"
13 : #include "nsIComponentManager.h"
14 : #include "nsCommandGroup.h"
15 : #include "nsIControllerCommand.h"
16 : #include "nsCRT.h"
17 :
18 : class nsGroupsEnumerator : public nsISimpleEnumerator
19 : {
20 : public:
21 : explicit nsGroupsEnumerator(
22 : nsControllerCommandGroup::GroupsHashtable& aInHashTable);
23 :
24 : NS_DECL_ISUPPORTS
25 : NS_DECL_NSISIMPLEENUMERATOR
26 :
27 : protected:
28 : virtual ~nsGroupsEnumerator();
29 :
30 : nsresult Initialize();
31 :
32 : protected:
33 : nsControllerCommandGroup::GroupsHashtable& mHashTable;
34 : int32_t mIndex;
35 : const char** mGroupNames; // array of pointers to char16_t* in the hash table
36 : bool mInitted;
37 : };
38 :
39 : /* Implementation file */
40 0 : NS_IMPL_ISUPPORTS(nsGroupsEnumerator, nsISimpleEnumerator)
41 :
42 0 : nsGroupsEnumerator::nsGroupsEnumerator(
43 0 : nsControllerCommandGroup::GroupsHashtable& aInHashTable)
44 : : mHashTable(aInHashTable)
45 : , mIndex(-1)
46 : , mGroupNames(nullptr)
47 0 : , mInitted(false)
48 : {
49 0 : }
50 :
51 0 : nsGroupsEnumerator::~nsGroupsEnumerator()
52 : {
53 0 : delete[] mGroupNames;
54 0 : }
55 :
56 : NS_IMETHODIMP
57 0 : nsGroupsEnumerator::HasMoreElements(bool* aResult)
58 : {
59 0 : nsresult rv = NS_OK;
60 :
61 0 : NS_ENSURE_ARG_POINTER(aResult);
62 :
63 0 : if (!mInitted) {
64 0 : rv = Initialize();
65 0 : if (NS_FAILED(rv)) {
66 0 : return rv;
67 : }
68 : }
69 :
70 0 : *aResult = (mIndex < static_cast<int32_t>(mHashTable.Count()) - 1);
71 0 : return NS_OK;
72 : }
73 :
74 : NS_IMETHODIMP
75 0 : nsGroupsEnumerator::GetNext(nsISupports** aResult)
76 : {
77 0 : nsresult rv = NS_OK;
78 :
79 0 : NS_ENSURE_ARG_POINTER(aResult);
80 :
81 0 : if (!mInitted) {
82 0 : rv = Initialize();
83 0 : if (NS_FAILED(rv)) {
84 0 : return rv;
85 : }
86 : }
87 :
88 0 : mIndex++;
89 0 : if (mIndex >= static_cast<int32_t>(mHashTable.Count())) {
90 0 : return NS_ERROR_FAILURE;
91 : }
92 :
93 0 : const char* thisGroupName = mGroupNames[mIndex];
94 :
95 : nsCOMPtr<nsISupportsCString> supportsString =
96 0 : do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
97 0 : if (NS_FAILED(rv)) {
98 0 : return rv;
99 : }
100 :
101 0 : supportsString->SetData(nsDependentCString(thisGroupName));
102 0 : return CallQueryInterface(supportsString, aResult);
103 : }
104 :
105 : nsresult
106 0 : nsGroupsEnumerator::Initialize()
107 : {
108 0 : if (mInitted) {
109 0 : return NS_OK;
110 : }
111 :
112 0 : mGroupNames = new const char*[mHashTable.Count()];
113 0 : if (!mGroupNames) {
114 0 : return NS_ERROR_OUT_OF_MEMORY;
115 : }
116 :
117 0 : mIndex = 0;
118 0 : for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
119 0 : mGroupNames[mIndex] = iter.Key().Data();
120 0 : mIndex++;
121 : }
122 :
123 0 : mIndex = -1;
124 0 : mInitted = true;
125 0 : return NS_OK;
126 : }
127 :
128 : class nsNamedGroupEnumerator : public nsISimpleEnumerator
129 : {
130 : public:
131 : explicit nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray);
132 :
133 : NS_DECL_ISUPPORTS
134 : NS_DECL_NSISIMPLEENUMERATOR
135 :
136 : protected:
137 : virtual ~nsNamedGroupEnumerator();
138 :
139 : nsTArray<nsCString>* mGroupArray;
140 : int32_t mIndex;
141 : };
142 :
143 0 : nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray)
144 : : mGroupArray(aInArray)
145 0 : , mIndex(-1)
146 : {
147 0 : }
148 :
149 0 : nsNamedGroupEnumerator::~nsNamedGroupEnumerator()
150 : {
151 0 : }
152 :
153 0 : NS_IMPL_ISUPPORTS(nsNamedGroupEnumerator, nsISimpleEnumerator)
154 :
155 : NS_IMETHODIMP
156 0 : nsNamedGroupEnumerator::HasMoreElements(bool* aResult)
157 : {
158 0 : NS_ENSURE_ARG_POINTER(aResult);
159 :
160 0 : int32_t arrayLen = mGroupArray ? mGroupArray->Length() : 0;
161 0 : *aResult = (mIndex < arrayLen - 1);
162 0 : return NS_OK;
163 : }
164 :
165 : NS_IMETHODIMP
166 0 : nsNamedGroupEnumerator::GetNext(nsISupports** aResult)
167 : {
168 0 : NS_ENSURE_ARG_POINTER(aResult);
169 :
170 0 : if (!mGroupArray) {
171 0 : return NS_ERROR_FAILURE;
172 : }
173 :
174 0 : mIndex++;
175 0 : if (mIndex >= int32_t(mGroupArray->Length())) {
176 0 : return NS_ERROR_FAILURE;
177 : }
178 :
179 0 : const nsCString& thisGroupName = mGroupArray->ElementAt(mIndex);
180 :
181 : nsresult rv;
182 : nsCOMPtr<nsISupportsCString> supportsString =
183 0 : do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
184 0 : if (NS_FAILED(rv)) {
185 0 : return rv;
186 : }
187 :
188 0 : supportsString->SetData(thisGroupName);
189 0 : return CallQueryInterface(supportsString, aResult);
190 : }
191 :
192 0 : NS_IMPL_ISUPPORTS(nsControllerCommandGroup, nsIControllerCommandGroup)
193 :
194 0 : nsControllerCommandGroup::nsControllerCommandGroup()
195 : {
196 0 : }
197 :
198 0 : nsControllerCommandGroup::~nsControllerCommandGroup()
199 : {
200 0 : ClearGroupsHash();
201 0 : }
202 :
203 : void
204 0 : nsControllerCommandGroup::ClearGroupsHash()
205 : {
206 0 : mGroupsHash.Clear();
207 0 : }
208 :
209 : NS_IMETHODIMP
210 0 : nsControllerCommandGroup::AddCommandToGroup(const char* aCommand,
211 : const char* aGroup)
212 : {
213 0 : nsDependentCString groupKey(aGroup);
214 0 : auto commandList = mGroupsHash.LookupForAdd(groupKey).OrInsert([]() {
215 0 : return new AutoTArray<nsCString, 8>();
216 0 : });
217 :
218 : #ifdef DEBUG
219 : nsCString* appended =
220 : #endif
221 0 : commandList->AppendElement(aCommand);
222 0 : NS_ASSERTION(appended, "Append failed");
223 :
224 0 : return NS_OK;
225 : }
226 :
227 : NS_IMETHODIMP
228 0 : nsControllerCommandGroup::RemoveCommandFromGroup(const char* aCommand,
229 : const char* aGroup)
230 : {
231 0 : nsDependentCString groupKey(aGroup);
232 0 : nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
233 0 : if (!commandList) {
234 0 : return NS_OK; // no group
235 : }
236 :
237 0 : uint32_t numEntries = commandList->Length();
238 0 : for (uint32_t i = 0; i < numEntries; i++) {
239 0 : nsCString commandString = commandList->ElementAt(i);
240 0 : if (nsDependentCString(aCommand) != commandString) {
241 0 : commandList->RemoveElementAt(i);
242 0 : break;
243 : }
244 : }
245 0 : return NS_OK;
246 : }
247 :
248 : NS_IMETHODIMP
249 0 : nsControllerCommandGroup::IsCommandInGroup(const char* aCommand,
250 : const char* aGroup, bool* aResult)
251 : {
252 0 : NS_ENSURE_ARG_POINTER(aResult);
253 0 : *aResult = false;
254 :
255 0 : nsDependentCString groupKey(aGroup);
256 0 : nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
257 0 : if (!commandList) {
258 0 : return NS_OK; // no group
259 : }
260 :
261 0 : uint32_t numEntries = commandList->Length();
262 0 : for (uint32_t i = 0; i < numEntries; i++) {
263 0 : nsCString commandString = commandList->ElementAt(i);
264 0 : if (nsDependentCString(aCommand) != commandString) {
265 0 : *aResult = true;
266 0 : break;
267 : }
268 : }
269 0 : return NS_OK;
270 : }
271 :
272 : NS_IMETHODIMP
273 0 : nsControllerCommandGroup::GetGroupsEnumerator(nsISimpleEnumerator** aResult)
274 : {
275 0 : RefPtr<nsGroupsEnumerator> groupsEnum = new nsGroupsEnumerator(mGroupsHash);
276 :
277 0 : groupsEnum.forget(aResult);
278 0 : return NS_OK;
279 : }
280 :
281 : NS_IMETHODIMP
282 0 : nsControllerCommandGroup::GetEnumeratorForGroup(const char* aGroup,
283 : nsISimpleEnumerator** aResult)
284 : {
285 0 : nsDependentCString groupKey(aGroup);
286 0 : nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey); // may be null
287 :
288 : RefPtr<nsNamedGroupEnumerator> theGroupEnum =
289 0 : new nsNamedGroupEnumerator(commandList);
290 :
291 0 : theGroupEnum.forget(aResult);
292 0 : return NS_OK;
293 : }
|