sbLibraryConstraints.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include "sbLibraryConstraints.h"
28 #include "sbLibraryCID.h"
29 
30 #include <nsAutoPtr.h>
31 #include <nsArrayEnumerator.h>
32 #include <nsCOMArray.h>
33 #include <nsIClassInfoImpl.h>
34 #include <nsINetUtil.h>
35 #include <nsIObjectInputStream.h>
36 #include <nsIObjectOutputStream.h>
37 #include <nsIProgrammingLanguage.h>
38 #include <nsIStringEnumerator.h>
39 #include <nsMemory.h>
40 #include <nsServiceManagerUtils.h>
41 
43 #include <sbStringUtils.h>
44 
75 /*
76  * sbLibraryConstraintBuilder
77  */
80 
81 
82 static inline nsresult CheckStringAndSkip(const nsAString & aSource,
83  PRUint32 & offset,
84  const nsAString & aSubstring)
85 {
86  if (!Substring(aSource, offset, aSubstring.Length()).Equals(aSubstring)) {
87  return NS_ERROR_ILLEGAL_VALUE;
88  }
89  offset += aSubstring.Length();
90  return NS_OK;
91 }
92 
93 /* sbILibraryConstraintBuilder parseFromString (in AString aSerializedConstraint); */
94 NS_IMETHODIMP
95 sbLibraryConstraintBuilder::ParseFromString(const nsAString & aConstraint,
97 {
98  NS_ENSURE_ARG_POINTER(_retval);
99 
100  nsresult rv;
101  PRUint32 offset = 0, next;
102 
103  rv = EnsureConstraint();
104  NS_ENSURE_SUCCESS(rv, rv);
105 
106  PRUint32 groupCount;
107  rv = mConstraint->GetGroupCount(&groupCount);
108  NS_ENSURE_SUCCESS(rv, rv);
109 
110  NS_ENSURE_TRUE(groupCount == 1, NS_ERROR_ALREADY_INITIALIZED);
111 
112  nsCOMPtr<sbILibraryConstraintGroup> group;
113  rv = mConstraint->GetGroup(0, getter_AddRefs(group));
114  NS_ENSURE_SUCCESS(rv, rv);
115 
116  nsCOMPtr<nsIStringEnumerator> props;
117  rv = group->GetProperties(getter_AddRefs(props));
118  NS_ENSURE_SUCCESS(rv, rv);
119 
120  PRBool hasMore;
121  rv = props->HasMore(&hasMore);
122  NS_ENSURE_SUCCESS(rv, rv);
123  NS_ENSURE_FALSE(hasMore, NS_ERROR_ALREADY_INITIALIZED);
124 
125  nsCOMPtr<nsINetUtil> netUtil =
126  do_GetService("@mozilla.org/network/util;1", &rv);
127  NS_ENSURE_SUCCESS(rv, rv);
128 
129  rv = CheckStringAndSkip(aConstraint, offset, NS_LITERAL_STRING("[{\""));
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  do {
133  // find the leading " at the end of the of property name
134  next = aConstraint.FindChar(PRUnichar('"'), offset);
135  if (next < 0) {
136  return NS_ERROR_ILLEGAL_VALUE;
137  }
138  // get the property name
139  nsString property(Substring(aConstraint, offset, next - offset));
140  offset = next + 1;
141 
142  // check for the start of the values
143  rv = CheckStringAndSkip(aConstraint, offset, NS_LITERAL_STRING(": [\""));
144  NS_ENSURE_SUCCESS(rv, rv);
145 
146  nsAutoPtr<sbStringArray> array(new sbStringArray);
147  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
148 
149  while (true) {
150  // look for the " at the end of the value
151  next = aConstraint.FindChar(PRUnichar('"'), offset);
152  if (next < 0) {
153  return NS_ERROR_ILLEGAL_VALUE;
154  }
155  nsString value(Substring(aConstraint, offset, next - offset));
156  // we need to unescape the string
157  nsCString unescapedValue;
158  rv = netUtil->UnescapeString(NS_ConvertUTF16toUTF8(value),
159  nsINetUtil::ESCAPE_XALPHAS,
160  unescapedValue);
161  NS_ENSURE_SUCCESS(rv, rv);
162  nsString* added = array->AppendElement(NS_ConvertUTF8toUTF16(unescapedValue));
163  NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
164  offset = next + 1;
165  if (Substring(aConstraint, offset, 1).EqualsLiteral("]")) {
166  // end of the values
167  ++offset;
168  break;
169  }
170  rv = CheckStringAndSkip(aConstraint, offset, NS_LITERAL_STRING(", \""));
171  NS_ENSURE_SUCCESS(rv, rv);
172  }
173 
174  rv = mConstraint->AddToCurrent(property, array);
175  NS_ENSURE_SUCCESS(rv, rv);
176  array.forget();
177 
178  // check for end of group
179  if (Substring(aConstraint, offset).EqualsLiteral("}]")) {
180  // end of the group
181  break;
182  }
183  rv = CheckStringAndSkip(aConstraint, offset, NS_LITERAL_STRING("}, {\""));
184  NS_ENSURE_SUCCESS(rv, rv);
185  rv = mConstraint->Intersect();
186  NS_ENSURE_SUCCESS(rv, rv);
187 
188  } while (true);
189  NS_ENSURE_TRUE(offset == aConstraint.Length() - 2, NS_ERROR_ILLEGAL_VALUE);
190 
191  NS_ADDREF(*_retval = this);
192  return NS_OK;
193 }
194 
195 NS_IMETHODIMP
196 sbLibraryConstraintBuilder::IncludeConstraint(sbILibraryConstraint* aConstraint,
197  sbILibraryConstraintBuilder** _retval)
198 {
199  NS_ENSURE_ARG_POINTER(aConstraint);
200  nsresult rv;
201 
202  rv = EnsureConstraint();
203  NS_ENSURE_SUCCESS(rv, rv);
204 
205  PRUint32 groupCount;
206  rv = aConstraint->GetGroupCount(&groupCount);
207  NS_ENSURE_SUCCESS(rv, rv);
208 
209  for (PRUint32 i = 0; i < groupCount; i++) {
210  nsCOMPtr<sbILibraryConstraintGroup> group;
211  rv = aConstraint->GetGroup(i, getter_AddRefs(group));
212  NS_ENSURE_SUCCESS(rv, rv);
213 
214  nsCOMPtr<nsIStringEnumerator> properties;
215  rv = group->GetProperties(getter_AddRefs(properties));
216  NS_ENSURE_SUCCESS(rv, rv);
217 
218  PRBool hasMore;
219  while (NS_SUCCEEDED(properties->HasMore(&hasMore)) && hasMore) {
220  nsString property;
221  rv = properties->GetNext(property);
222  NS_ENSURE_SUCCESS(rv, rv);
223 
224  nsCOMPtr<nsIStringEnumerator> values;
225  rv = group->GetValues(property, getter_AddRefs(values));
226  NS_ENSURE_SUCCESS(rv, rv);
227 
228  rv = IncludeList(property, values, nsnull);
229  NS_ENSURE_SUCCESS(rv, rv);
230  }
231 
232  if (i + 1 < groupCount) {
233  rv = Intersect(nsnull);
234  NS_ENSURE_SUCCESS(rv, rv);
235  }
236 
237  }
238 
239  if (_retval) {
240  NS_ADDREF(*_retval = this);
241  }
242 
243  return NS_OK;
244 }
245 
246 NS_IMETHODIMP
247 sbLibraryConstraintBuilder::Include(const nsAString& aProperty,
248  const nsAString& aValue,
249  sbILibraryConstraintBuilder** _retval)
250 {
251  NS_ENSURE_ARG(!aProperty.IsEmpty());
252 
253  nsresult rv;
254 
255  rv = EnsureConstraint();
256  NS_ENSURE_SUCCESS(rv, rv);
257 
258  // TODO: VALIDATE VALUES
259  nsAutoPtr<sbStringArray> array(new sbStringArray);
260  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
261 
262  nsString* success = array->AppendElement(aValue);
263  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
264 
265  // Transfer ownership of array to the callee
266  rv = mConstraint->AddToCurrent(aProperty, array.forget());
267  NS_ENSURE_SUCCESS(rv, rv);
268 
269  if (_retval) {
270  NS_ADDREF(*_retval = this);
271  }
272 
273  return NS_OK;
274 }
275 
276 NS_IMETHODIMP
277 sbLibraryConstraintBuilder::IncludeList(const nsAString& aProperty,
278  nsIStringEnumerator* aValues,
279  sbILibraryConstraintBuilder** _retval)
280 {
281  NS_ENSURE_ARG(!aProperty.IsEmpty());
282 
283  nsresult rv;
284 
285  rv = EnsureConstraint();
286  NS_ENSURE_SUCCESS(rv, rv);
287 
288  // TODO: VALIDATE VALUES
289  nsAutoPtr<sbStringArray> array(new sbStringArray);
290  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
291 
292  PRBool hasMore;
293  while (NS_SUCCEEDED(aValues->HasMore(&hasMore)) && hasMore) {
294  nsString value;
295  rv = aValues->GetNext(value);
296  NS_ENSURE_SUCCESS(rv, rv);
297 
298  nsString* success = array->AppendElement(value);
299  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
300  }
301 
302  // Transfer ownership of array to the callee
303  rv = mConstraint->AddToCurrent(aProperty, array.forget());
304  NS_ENSURE_SUCCESS(rv, rv);
305 
306  if (_retval) {
307  NS_ADDREF(*_retval = this);
308  }
309 
310  return NS_OK;
311 }
312 
313 NS_IMETHODIMP
314 sbLibraryConstraintBuilder::Intersect(sbILibraryConstraintBuilder** _retval)
315 {
316  nsresult rv;
317 
318  rv = EnsureConstraint();
319  NS_ENSURE_SUCCESS(rv, rv);
320 
321  NS_ENSURE_STATE(mConstraint->IsValid());
322 
323  rv = mConstraint->Intersect();
324  NS_ENSURE_SUCCESS(rv, rv);
325 
326  if (_retval) {
327  NS_ADDREF(*_retval = this);
328  }
329 
330  return NS_OK;
331 }
332 
333 NS_IMETHODIMP
334 sbLibraryConstraintBuilder::Get(sbILibraryConstraint** _retval)
335 {
336  NS_ENSURE_ARG_POINTER(_retval);
337 
338  nsresult rv;
339 
340  rv = EnsureConstraint();
341  NS_ENSURE_SUCCESS(rv, rv);
342 
343  NS_ENSURE_STATE(mConstraint->IsValid());
344 
345  NS_ADDREF(*_retval = mConstraint);
346  mConstraint = nsnull;
347 
348  return NS_OK;
349 }
350 
351 nsresult
352 sbLibraryConstraintBuilder::EnsureConstraint()
353 {
354  if (mConstraint) {
355  return NS_OK;
356  }
357 
358  nsRefPtr<sbLibraryConstraint> constraint = new sbLibraryConstraint();
359  NS_ENSURE_TRUE(constraint, NS_ERROR_OUT_OF_MEMORY);
360 
361  nsresult rv = constraint->Init();
362  NS_ENSURE_SUCCESS(rv, rv);
363 
364  mConstraint = constraint;
365 
366  return NS_OK;
367 }
368 
369 /*
370  * sbLibraryConstraint
371  */
372 
373 static NS_DEFINE_CID(kLibraryConstraintCID,
375 
379  nsIClassInfo)
380 
384  nsIClassInfo)
385 
386 sbLibraryConstraint::sbLibraryConstraint() :
387  mInitialized(PR_FALSE)
388 {
389 }
390 
391 NS_IMETHODIMP
392 sbLibraryConstraint::GetGroupCount(PRUint32* aGroupCount)
393 {
394  NS_ENSURE_STATE(mInitialized);
395  NS_ENSURE_ARG_POINTER(aGroupCount);
396 
397  *aGroupCount = mConstraint.Length();
398 
399  return NS_OK;
400 }
401 
402 NS_IMETHODIMP
403 sbLibraryConstraint::GetGroups(nsISimpleEnumerator** aGroups)
404 {
405  NS_ENSURE_STATE(mInitialized);
406  NS_ENSURE_ARG_POINTER(aGroups);
407 
408  nsCOMArray<sbILibraryConstraintGroup> array;
409  PRUint32 length = mConstraint.Length();
410  for (PRUint32 i = 0; i < length; i++) {
411  PRBool success = array.AppendObject(mConstraint[i]);
412  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
413  }
414 
415  nsresult rv = NS_NewArrayEnumerator(aGroups, array);
416  NS_ENSURE_SUCCESS(rv, rv);
417  return NS_OK;
418 }
419 
420 NS_IMETHODIMP
421 sbLibraryConstraint::GetGroup(PRUint32 aIndex,
422  sbILibraryConstraintGroup** _retval)
423 {
424  NS_ENSURE_STATE(mInitialized);
425  NS_ENSURE_ARG_POINTER(_retval);
426  NS_ENSURE_TRUE(aIndex < mConstraint.Length(), NS_ERROR_INVALID_ARG);
427 
428  NS_ADDREF(*_retval = mConstraint[aIndex]);
429  return NS_OK;
430 }
431 
432 NS_IMETHODIMP
433 sbLibraryConstraint::Equals(sbILibraryConstraint* aOtherConstraint,
434  PRBool* _retval)
435 {
436  NS_ENSURE_STATE(mInitialized);
437  NS_ENSURE_ARG_POINTER(_retval);
438 
439  nsresult rv;
440 
441  if (!aOtherConstraint) {
442  *_retval = PR_FALSE;
443  return NS_OK;
444  }
445 
446  PRUint32 groupCount;
447  rv = aOtherConstraint->GetGroupCount(&groupCount);
448  NS_ENSURE_SUCCESS(rv, rv);
449 
450  if (mConstraint.Length() != groupCount) {
451  *_retval = PR_FALSE;
452  return NS_OK;
453  }
454 
455  nsCOMArray<sbILibraryConstraintGroup> matchesRemaining(groupCount);
456  for (PRUint32 i = 0; i < groupCount; i++) {
457 
458  nsCOMPtr<sbILibraryConstraintGroup> otherGroup;
459  rv = aOtherConstraint->GetGroup(i, getter_AddRefs(otherGroup));
460  NS_ENSURE_SUCCESS(rv, rv);
461 
462  PRBool success = matchesRemaining.AppendObject(otherGroup);
463  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
464  }
465 
466  for (PRUint32 i = 0; i < groupCount; i++) {
467  for (PRInt32 j = 0; j < matchesRemaining.Count(); j++) {
468  PRBool equals;
469  rv = mConstraint[i]->Equals(matchesRemaining[j], &equals);
470  NS_ENSURE_SUCCESS(rv, rv);
471 
472  if (equals) {
473  matchesRemaining.RemoveObjectAt(j);
474  }
475  }
476  }
477 
478  *_retval = matchesRemaining.Count() == 0;
479  return NS_OK;
480 }
481 
482 NS_IMETHODIMP
483 sbLibraryConstraint::ToString(nsAString& _retval)
484 {
485  NS_ENSURE_STATE(mInitialized);
486 
487  nsString buff;
488  buff.AssignLiteral("[");
489 
490  PRUint32 length = mConstraint.Length();
491  for (PRUint32 i = 0; i < length; i++) {
492 
493  nsString temp;
494  nsresult rv = mConstraint[i]->ToString(temp);
495  NS_ENSURE_SUCCESS(rv, rv);
496 
497  buff.Append(temp);
498  if (i + 1 < length) {
499  buff.AppendLiteral(", ");
500  }
501 
502  }
503 
504  buff.AppendLiteral("]");
505  _retval = buff;
506  return NS_OK;
507 }
508 
509 // nsISerializable
510 NS_IMETHODIMP
511 sbLibraryConstraint::Read(nsIObjectInputStream* aStream)
512 {
513  NS_ENSURE_STATE(!mInitialized);
514  NS_ENSURE_ARG_POINTER(aStream);
515 
516  nsresult rv;
517 
518  PRUint32 length;
519  rv = aStream->Read32(&length);
520  NS_ENSURE_SUCCESS(rv, rv);
521 
522  for (PRUint32 i = 0; i < length; i++) {
524  NS_ENSURE_TRUE(group, NS_ERROR_OUT_OF_MEMORY);
525 
526  nsresult rv = group->Read(aStream);
527  NS_ENSURE_SUCCESS(rv, rv);
528 
529  sbConstraintGroupRefPtr* success = mConstraint.AppendElement(group);
530  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
531  }
532 
533  mInitialized = PR_TRUE;
534 
535  return NS_OK;
536 }
537 
538 NS_IMETHODIMP
539 sbLibraryConstraint::Write(nsIObjectOutputStream* aStream)
540 {
541  NS_ENSURE_STATE(mInitialized);
542  NS_ENSURE_ARG_POINTER(aStream);
543 
544  nsresult rv;
545 
546  PRUint32 length = mConstraint.Length();
547  rv = aStream->Write32(length);
548  NS_ENSURE_SUCCESS(rv, rv);
549 
550  for (PRUint32 i = 0; i < length; i++) {
551  rv = mConstraint[i]->Write(aStream);
552  NS_ENSURE_SUCCESS(rv, rv);
553  }
554 
555  return NS_OK;
556 }
557 
558 // nsIClassInfo
559 NS_IMETHODIMP
560 sbLibraryConstraint::GetInterfaces(PRUint32* count, nsIID*** array)
561 {
562  return NS_CI_INTERFACE_GETTER_NAME(sbLibraryConstraint)(count, array);
563 }
564 
565 NS_IMETHODIMP
566 sbLibraryConstraint::GetHelperForLanguage(PRUint32 language,
567  nsISupports** _retval)
568 {
569  *_retval = nsnull;
570  return NS_OK;
571 }
572 
573 NS_IMETHODIMP
574 sbLibraryConstraint::GetContractID(char** aContractID)
575 {
576  *aContractID = nsnull;
577  return NS_OK;
578 }
579 
580 NS_IMETHODIMP
581 sbLibraryConstraint::GetClassDescription(char** aClassDescription)
582 {
583  *aClassDescription = nsnull;
584  return NS_OK;
585 }
586 
587 NS_IMETHODIMP
588 sbLibraryConstraint::GetClassID(nsCID** aClassID)
589 {
590  *aClassID = nsnull;
591  return NS_OK;
592 }
593 
594 NS_IMETHODIMP
595 sbLibraryConstraint::GetImplementationLanguage(PRUint32* aImplementationLanguage)
596 {
597  *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
598  return NS_OK;
599 }
600 
601 NS_IMETHODIMP
602 sbLibraryConstraint::GetFlags(PRUint32* aFlags)
603 {
604  *aFlags = 0;
605  return NS_OK;
606 }
607 
608 NS_IMETHODIMP
609 sbLibraryConstraint::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
610 {
611  NS_ENSURE_ARG_POINTER(aClassIDNoAlloc);
612  *aClassIDNoAlloc = kLibraryConstraintCID;
613  return NS_OK;
614 }
615 
616 nsresult
617 sbLibraryConstraint::Init()
618 {
619  mInitialized = PR_TRUE;
620  return Intersect();
621 }
622 
623 nsresult
624 sbLibraryConstraint::Intersect()
625 {
627  NS_ENSURE_TRUE(group, NS_ERROR_OUT_OF_MEMORY);
628 
629  nsresult rv = group->Init();
630  NS_ENSURE_SUCCESS(rv, rv);
631 
632  sbConstraintGroupRefPtr* success = mConstraint.AppendElement(group);
633  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
634 
635  return NS_OK;
636 }
637 
638 nsresult
639 sbLibraryConstraint::AddToCurrent(const nsAString& aProperty,
640  sbStringArray* aArray)
641 {
642  PRUint32 length = mConstraint.Length();
643  NS_ENSURE_TRUE(length, NS_ERROR_UNEXPECTED);
644 
645  nsresult rv = mConstraint[length - 1]->Add(aProperty, aArray);
646  NS_ENSURE_SUCCESS(rv, rv);
647 
648  return NS_OK;
649 }
650 
651 PRBool
652 sbLibraryConstraint::IsValid()
653 {
654  PRUint32 length = mConstraint.Length();
655  NS_ENSURE_TRUE(length, NS_ERROR_UNEXPECTED);
656 
657  return !mConstraint[length - 1]->IsEmpty();
658 }
659 
660 /*
661  * sbLibraryConstraintGroup
662  */
663 
666 
668  mInitialized(PR_FALSE)
669 {
670 }
671 
672 /* static */ PLDHashOperator PR_CALLBACK
673 sbLibraryConstraintGroup::AddKeysToArrayCallback(nsStringHashKey::KeyType aKey,
674  sbStringArray* aEntry,
675  void* aUserData)
676 {
677  NS_ASSERTION(aEntry, "Null entry in the hash?!");
678 
679  sbStringArray* array = static_cast<sbStringArray*>(aUserData);
680  NS_ASSERTION(array, "null userdata");
681 
682  nsString* success = array->AppendElement(aKey);
683  NS_ENSURE_TRUE(success, PL_DHASH_STOP);
684 
685  return PL_DHASH_NEXT;
686 }
687 
688 NS_IMETHODIMP
689 sbLibraryConstraintGroup::GetProperties(nsIStringEnumerator** aProperties)
690 {
691  NS_ENSURE_STATE(mInitialized);
692  NS_ENSURE_ARG_POINTER(aProperties);
693 
694  nsAutoTArray<nsString, 10> array;
695  mConstraintGroup.EnumerateRead(AddKeysToArrayCallback, &array);
696  nsCOMPtr<nsIStringEnumerator> enumerator =
697  new sbTArrayStringEnumerator(&array);
698  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
699 
700  enumerator.forget(aProperties);
701 
702  return NS_OK;
703 }
704 
705 NS_IMETHODIMP
706 sbLibraryConstraintGroup::GetValues(const nsAString& aProperty,
707  nsIStringEnumerator** _retval)
708 {
709  NS_ENSURE_STATE(mInitialized);
710  NS_ENSURE_ARG_POINTER(_retval);
711 
713  if (!mConstraintGroup.Get(aProperty, &array)) {
714  return NS_ERROR_NOT_AVAILABLE;
715  }
716 
717  nsCOMPtr<nsIStringEnumerator> enumerator =
718  new sbTArrayStringEnumerator(array);
719  NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
720 
721  enumerator.forget(_retval);
722 
723  return NS_OK;
724 }
725 
726 NS_IMETHODIMP
727 sbLibraryConstraintGroup::HasProperty(const nsAString& aProperty,
728  PRBool* _retval)
729 {
730  NS_ENSURE_STATE(mInitialized);
731  NS_ENSURE_ARG_POINTER(_retval);
732 
733  *_retval = mConstraintGroup.Get(aProperty, nsnull);
734 
735  return NS_OK;
736 }
737 
738 NS_IMETHODIMP
739 sbLibraryConstraintGroup::Equals(sbILibraryConstraintGroup* aOtherGroup,
740  PRBool* _retval)
741 {
742  NS_ENSURE_STATE(mInitialized);
743  NS_ENSURE_ARG_POINTER(_retval);
744 
745  nsresult rv;
746  *_retval = PR_FALSE;
747 
748  if (!aOtherGroup) {
749  return NS_OK;
750  }
751 
752  nsCOMPtr<nsIStringEnumerator> properties;
753  rv = GetProperties(getter_AddRefs(properties));
754  NS_ENSURE_SUCCESS(rv, rv);
755 
756  nsCOMPtr<nsIStringEnumerator> otherProperties;
757  rv = aOtherGroup->GetProperties(getter_AddRefs(otherProperties));
758  NS_ENSURE_SUCCESS(rv, rv);
759 
760  PRBool equals;
761  rv = SB_StringEnumeratorEquals(properties, otherProperties, &equals);
762  NS_ENSURE_SUCCESS(rv, rv);
763 
764  if (!equals) {
765  return NS_OK;
766  }
767 
768  sbStringArray propertyArray;
769  mConstraintGroup.EnumerateRead(AddKeysToArrayCallback, &propertyArray);
770  PRUint32 propertyCount = propertyArray.Length();
771  NS_ENSURE_TRUE(propertyCount == mConstraintGroup.Count(),
772  NS_ERROR_UNEXPECTED);
773 
774  for (PRUint32 i = 0; i < propertyCount; i++) {
775 
776  nsCOMPtr<nsIStringEnumerator> values;
777  rv = GetValues(propertyArray[i], getter_AddRefs(values));
778  NS_ENSURE_SUCCESS(rv, rv);
779 
780  nsCOMPtr<nsIStringEnumerator> otherValues;
781  rv = aOtherGroup->GetValues(propertyArray[i], getter_AddRefs(otherValues));
782  NS_ENSURE_SUCCESS(rv, rv);
783 
784  rv = SB_StringEnumeratorEquals(values, otherValues, &equals);
785  NS_ENSURE_SUCCESS(rv, rv);
786 
787  if (!equals) {
788  return NS_OK;
789  }
790  }
791 
792  *_retval = PR_TRUE;
793  return NS_OK;
794 }
795 
796 NS_IMETHODIMP
797 sbLibraryConstraintGroup::ToString(nsAString& _retval)
798 {
799  NS_ENSURE_STATE(mInitialized);
800  nsString buff(NS_LITERAL_STRING("{"));
801  nsCString cbuff;
802  nsresult rv;
803 
804  nsAutoTArray<nsString, 10> properties;
805  mConstraintGroup.EnumerateRead(AddKeysToArrayCallback, &properties);
806 
807  nsCOMPtr<nsINetUtil> netUtil =
808  do_GetService("@mozilla.org/network/util;1", &rv);
809  NS_ENSURE_SUCCESS(rv, rv);
810 
811  PRUint32 propertyCount = properties.Length();
812  for (PRUint32 i = 0; i < propertyCount; i++) {
813  buff.AppendLiteral("\"");
814  buff.Append(properties[i]);
815  buff.AppendLiteral("\": [");
816  sbStringArray* values;
817  PRBool success = mConstraintGroup.Get(properties[i], &values);
818  NS_ENSURE_SUCCESS(success, NS_ERROR_UNEXPECTED);
819  PRUint32 valueCount = values->Length();
820  for (PRUint32 j = 0; j < valueCount; j++) {
821  buff.AppendLiteral("\"");
822  // we need to escape all quotes in the values
823  rv = netUtil->EscapeString(NS_ConvertUTF16toUTF8(values->ElementAt(j)),
824  nsINetUtil::ESCAPE_XALPHAS,
825  cbuff);
826  NS_ENSURE_SUCCESS(rv, rv);
827  buff.Append(NS_ConvertUTF8toUTF16(cbuff));
828  buff.AppendLiteral("\"");
829 
830  if (j + 1 < valueCount) {
831  buff.AppendLiteral(", ");
832  }
833  }
834  buff.AppendLiteral("]");
835 
836  if (i + 1 < propertyCount) {
837  buff.AppendLiteral(", ");
838  }
839  }
840 
841  buff.AppendLiteral("}");
842  _retval = buff;
843 
844  return NS_OK;
845 }
846 
847 nsresult
848 sbLibraryConstraintGroup::Init()
849 {
850  PRBool success = mConstraintGroup.Init();
851  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
852 
853  mInitialized = PR_TRUE;
854 
855  return NS_OK;
856 }
857 
858 inline PRBool
859 sbLibraryConstraintGroup::IsEmpty()
860 {
861  return mConstraintGroup.Count() == 0;
862 }
863 
864 nsresult
865 sbLibraryConstraintGroup::Add(const nsAString& aProperty,
866  sbStringArray* aArray)
867 {
868  NS_ASSERTION(aArray, "sbStringArray is null");
869  nsAutoPtr<sbStringArray> array(aArray);
870 
871  sbStringArray* existing;
872  if (mConstraintGroup.Get(aProperty, &existing)) {
873  nsString* success = existing->AppendElements(*array);
874  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
875  // Let the nsAutoPtr delete the array since we've copied its contents
876  // in to the hashtable
877  }
878  else {
879  PRBool success = mConstraintGroup.Put(aProperty, array);
880  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
881 
882  // We've transfered ownership to the hashtable so forget it
883  array.forget();
884  }
885 
886  return NS_OK;
887 }
888 
889 nsresult
890 sbLibraryConstraintGroup::Read(nsIObjectInputStream* aStream)
891 {
892  NS_ENSURE_STATE(!mInitialized);
893  NS_ASSERTION(aStream, "aStream is null");
894 
895  nsresult rv;
896 
897  rv = Init();
898  NS_ENSURE_SUCCESS(rv, rv);
899 
900  PRUint32 length;
901  rv = aStream->Read32(&length);
902  NS_ENSURE_SUCCESS(rv, rv);
903 
904  for (PRUint32 i = 0; i < length; i++) {
905  nsString property;
906  rv = aStream->ReadString(property);
907  NS_ENSURE_SUCCESS(rv, rv);
908 
909  PRUint32 valueCount;
910  rv = aStream->Read32(&valueCount);
911  NS_ENSURE_SUCCESS(rv, rv);
912 
913  sbStringArray* array = new sbStringArray;
914  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
915 
916  for (PRUint32 j = 0; j < valueCount; j++) {
917  nsString value;
918  rv = aStream->ReadString(value);
919  NS_ENSURE_SUCCESS(rv, rv);
920 
921  nsString* added = array->AppendElement(value);
922  NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
923  }
924 
925  PRBool success = mConstraintGroup.Put(property, array);
926  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
927  }
928 
929  return NS_OK;
930 }
931 
932 nsresult
933 sbLibraryConstraintGroup::Write(nsIObjectOutputStream* aStream)
934 {
935  NS_ENSURE_STATE(mInitialized);
936  NS_ASSERTION(aStream, "aStream is null");
937  nsresult rv;
938 
939  nsAutoTArray<nsString, 10> array;
940  mConstraintGroup.EnumerateRead(AddKeysToArrayCallback, &array);
941 
942  PRUint32 length = array.Length();
943  rv = aStream->Write32(length);
944  NS_ENSURE_SUCCESS(rv, rv);
945 
946  for (PRUint32 i = 0; i < length; i++) {
947  rv = aStream->WriteWStringZ(array[i].BeginReading());
948  NS_ENSURE_SUCCESS(rv, rv);
949 
950  sbStringArray* values;
951  PRBool success = mConstraintGroup.Get(array[i], &values);
952  NS_ENSURE_SUCCESS(success, NS_ERROR_UNEXPECTED);
953 
954  PRUint32 valueCount = values->Length();
955  rv = aStream->Write32(valueCount);
956  NS_ENSURE_SUCCESS(rv, rv);
957 
958  for (PRUint32 j = 0; j < valueCount; j++) {
959  rv = aStream->WriteWStringZ(values->ElementAt(j).BeginReading());
960  NS_ENSURE_SUCCESS(rv, rv);
961  }
962  }
963 
964  return NS_OK;
965 }
966 
967 static NS_DEFINE_CID(kLibrarySortCID,
969 
973  nsIClassInfo)
974 
978  nsIClassInfo)
979 
980 sbLibrarySort::sbLibrarySort() :
981  mInitialized(PR_FALSE),
982  mIsAscending(PR_FALSE)
983 {
984 }
985 
986 NS_IMETHODIMP
987 sbLibrarySort::Init(const nsAString& aProperty, PRBool aIsAscending)
988 {
989  NS_ENSURE_STATE(!mInitialized);
990  mProperty = aProperty;
991  mIsAscending = aIsAscending;
992  mInitialized = PR_TRUE;
993  return NS_OK;
994 }
995 
996 NS_IMETHODIMP
997 sbLibrarySort::GetProperty(nsAString& aProperty)
998 {
999  NS_ENSURE_STATE(mInitialized);
1000  aProperty = mProperty;
1001  return NS_OK;
1002 }
1003 
1004 NS_IMETHODIMP
1005 sbLibrarySort::GetIsAscending(PRBool* aIsAscending)
1006 {
1007  NS_ENSURE_STATE(mInitialized);
1008  NS_ENSURE_ARG_POINTER(aIsAscending);
1009 
1010  *aIsAscending = mIsAscending;
1011  return NS_OK;
1012 }
1013 
1014 NS_IMETHODIMP
1015 sbLibrarySort::ToString(nsAString& aString)
1016 {
1017  NS_ENSURE_STATE(mInitialized);
1018 
1019  nsString buff;
1020  buff.AssignLiteral("sort: property = '");
1021  buff.Append(mProperty);
1022  buff.AppendLiteral("' is ascending = ");
1023  buff.AppendLiteral(mIsAscending ? "yes" : "no");
1024 
1025  aString = buff;
1026  return NS_OK;
1027 }
1028 
1029 // nsISerializable
1030 NS_IMETHODIMP
1031 sbLibrarySort::Read(nsIObjectInputStream* aStream)
1032 {
1033  NS_ENSURE_ARG_POINTER(aStream);
1034 
1035  nsresult rv;
1036 
1037  rv = aStream->ReadString(mProperty);
1038  NS_ENSURE_SUCCESS(rv, rv);
1039 
1040  rv = aStream->ReadBoolean(&mIsAscending);
1041  NS_ENSURE_SUCCESS(rv, rv);
1042 
1043  mInitialized = PR_TRUE;
1044 
1045  return NS_OK;
1046 }
1047 
1048 NS_IMETHODIMP
1049 sbLibrarySort::Write(nsIObjectOutputStream* aStream)
1050 {
1051  NS_ENSURE_STATE(mInitialized);
1052  NS_ENSURE_ARG_POINTER(aStream);
1053 
1054  nsresult rv;
1055 
1056  rv = aStream->WriteWStringZ(mProperty.BeginReading());
1057  NS_ENSURE_SUCCESS(rv, rv);
1058 
1059  rv = aStream->WriteBoolean(mIsAscending);
1060  NS_ENSURE_SUCCESS(rv, rv);
1061 
1062  return NS_OK;
1063 }
1064 
1065 // nsIClassInfo
1066 NS_IMETHODIMP
1067 sbLibrarySort::GetInterfaces(PRUint32* count, nsIID*** array)
1068 {
1069  return NS_CI_INTERFACE_GETTER_NAME(sbLibrarySort)(count, array);
1070 }
1071 
1072 NS_IMETHODIMP
1073 sbLibrarySort::GetHelperForLanguage(PRUint32 language,
1074  nsISupports** _retval)
1075 {
1076  *_retval = nsnull;
1077  return NS_OK;
1078 }
1079 
1080 NS_IMETHODIMP
1081 sbLibrarySort::GetContractID(char** aContractID)
1082 {
1083  *aContractID = nsnull;
1084  return NS_OK;
1085 }
1086 
1087 NS_IMETHODIMP
1088 sbLibrarySort::GetClassDescription(char** aClassDescription)
1089 {
1090  *aClassDescription = nsnull;
1091  return NS_OK;
1092 }
1093 
1094 NS_IMETHODIMP
1095 sbLibrarySort::GetClassID(nsCID** aClassID)
1096 {
1097  *aClassID = nsnull;
1098  return NS_OK;
1099 }
1100 
1101 NS_IMETHODIMP
1102 sbLibrarySort::GetImplementationLanguage(PRUint32* aImplementationLanguage)
1103 {
1104  *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
1105  return NS_OK;
1106 }
1107 
1108 NS_IMETHODIMP
1109 sbLibrarySort::GetFlags(PRUint32* aFlags)
1110 {
1111  *aFlags = 0;
1112  return NS_OK;
1113 }
1114 
1115 NS_IMETHODIMP
1116 sbLibrarySort::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
1117 {
1118  NS_ENSURE_ARG_POINTER(aClassIDNoAlloc);
1119  *aClassIDNoAlloc = kLibrarySortCID;
1120  return NS_OK;
1121 }
1122 
return NS_OK
boolean equals(in sbILibraryConstraintGroup aOtherGroup)
onPageChanged aValue
Definition: FeedWriter.js:1395
nsTArray< nsString > sbStringArray
inArray array
nsresult SB_StringEnumeratorEquals(nsIStringEnumerator *aLeft, nsIStringEnumerator *aRight, PRBool *_retval)
NS_IMPL_CI_INTERFACE_GETTER3(sbMediaListEnumeratorWrapper, sbIMediaListEnumeratorWrapper, nsISimpleEnumerator, nsIClassInfo)
nsRefPtr< sbLibraryConstraintGroup > sbConstraintGroupRefPtr
PRUint32 const nsAString & aSubstring
#define SONGBIRD_LIBRARY_CONSTRAINT_CID
Definition: sbLibraryCID.h:56
var language
Definition: Info.js:44
readonly attribute unsigned long groupCount
static nsresult ToString(const nsDiscriminatedUnion &data, nsACString &outString)
Definition: sbVariant.cpp:861
PRUint32 & offset
var count
Definition: test_bug7406.js:32
static nsresult GetProperty(nsIPropertyBag2 *aProperties, nsAString const &aProp, nsAString &aValue)
function Init()
NS_IMPL_ISUPPORTS3(sbLibraryConstraint, sbILibraryConstraint, nsISerializable, nsIClassInfo) NS_IMPL_CI_INTERFACE_GETTER3(sbLibraryConstraint
boolean equals(in sbILibraryConstraint aOtherConstraint)
A sort that can be applied to a media list view.
StringArrayEnumerator prototype hasMore
countRef value
Definition: FeedWriter.js:1423
#define SONGBIRD_LIBRARYSORT_CID
Definition: sbLibraryCID.h:68
static NS_DEFINE_CID(kLibraryConstraintCID,{0x318e7d66, 0x59c4, 0x43d5,{0x8c, 0xf6, 0x5a, 0x51, 0x26, 0x3d, 0xb5, 0xd6}})
NS_IMPL_ISUPPORTS1(sbLibraryConstraintBuilder, sbILibraryConstraintBuilder) static inline nsresult CheckStringAndSkip(const nsAString &aSource
_getSelectedPageStyle s i
var group
readonly attribute nsIStringEnumerator properties
function next()