Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / xslt / xslt / txXPathResultComparator.cpp
blob470a55dc50324477b91e2207aabf27f37eb6296a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/FloatingPoint.h"
7 #include "mozilla/intl/Collator.h"
8 #include "mozilla/intl/LocaleService.h"
10 #include "txXPathResultComparator.h"
11 #include "txExpr.h"
12 #include "nsComponentManagerUtils.h"
13 #include "txCore.h"
15 using namespace mozilla;
16 using Collator = mozilla::intl::Collator;
18 #define kAscending (1 << 0)
19 #define kUpperFirst (1 << 1)
21 txResultStringComparator::txResultStringComparator(bool aAscending,
22 bool aUpperFirst,
23 const nsString& aLanguage) {
24 mSorting = 0;
25 if (aAscending) mSorting |= kAscending;
26 if (aUpperFirst) mSorting |= kUpperFirst;
27 nsresult rv = init(aLanguage);
28 if (NS_FAILED(rv)) NS_ERROR("Failed to initialize txResultStringComparator");
31 nsresult txResultStringComparator::init(const nsString& aLanguage) {
32 auto result =
33 aLanguage.IsEmpty()
34 ? mozilla::intl::LocaleService::TryCreateComponent<Collator>()
35 : mozilla::intl::LocaleService::TryCreateComponentWithLocale<
36 Collator>(NS_ConvertUTF16toUTF8(aLanguage).get());
38 NS_ENSURE_TRUE(result.isOk(), NS_ERROR_FAILURE);
39 auto collator = result.unwrap();
41 // Sort in a case-insensitive way, where "base" letters are considered
42 // equal, e.g: a = á, a = A, a ≠ b.
43 Collator::Options options{};
44 options.sensitivity = Collator::Sensitivity::Base;
45 auto optResult = collator->SetOptions(options);
46 NS_ENSURE_TRUE(optResult.isOk(), NS_ERROR_FAILURE);
48 mCollator = UniquePtr<const Collator>(collator.release());
49 return NS_OK;
52 nsresult txResultStringComparator::createSortableValue(Expr* aExpr,
53 txIEvalContext* aContext,
54 txObject*& aResult) {
55 UniquePtr<StringValue> val(new StringValue);
57 if (!mCollator) {
58 return NS_ERROR_FAILURE;
61 val->mString = MakeUnique<nsString>();
62 nsString& string = *val->mString;
63 nsresult rv = aExpr->evaluateToString(aContext, string);
64 NS_ENSURE_SUCCESS(rv, rv);
66 aResult = val.release();
68 return NS_OK;
71 int txResultStringComparator::compareValues(txObject* aVal1, txObject* aVal2) {
72 nsString& dval1 = *((StringValue*)aVal1)->mString;
73 nsString& dval2 = *((StringValue*)aVal2)->mString;
75 if (!mCollator) {
76 MOZ_ASSERT_UNREACHABLE("No mCollator");
77 return -1;
80 int32_t result = mCollator->CompareStrings(dval1, dval2);
82 return (mSorting & kAscending) ? result : -result;
85 txResultStringComparator::StringValue::StringValue() = default;
87 txResultStringComparator::StringValue::~StringValue() = default;
89 txResultNumberComparator::txResultNumberComparator(bool aAscending) {
90 mAscending = aAscending ? 1 : -1;
93 nsresult txResultNumberComparator::createSortableValue(Expr* aExpr,
94 txIEvalContext* aContext,
95 txObject*& aResult) {
96 UniquePtr<NumberValue> numval(new NumberValue);
98 RefPtr<txAExprResult> exprRes;
99 nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprRes));
100 NS_ENSURE_SUCCESS(rv, rv);
102 numval->mVal = exprRes->numberValue();
104 aResult = numval.release();
106 return NS_OK;
109 int txResultNumberComparator::compareValues(txObject* aVal1, txObject* aVal2) {
110 double dval1 = ((NumberValue*)aVal1)->mVal;
111 double dval2 = ((NumberValue*)aVal2)->mVal;
113 if (std::isnan(dval1)) return std::isnan(dval2) ? 0 : -mAscending;
115 if (std::isnan(dval2)) return mAscending;
117 if (dval1 == dval2) return 0;
119 return (dval1 < dval2) ? -mAscending : mAscending;