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"
12 #include "nsComponentManagerUtils.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
,
23 const nsString
& aLanguage
) {
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
) {
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());
52 nsresult
txResultStringComparator::createSortableValue(Expr
* aExpr
,
53 txIEvalContext
* aContext
,
55 UniquePtr
<StringValue
> val(new StringValue
);
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();
71 int txResultStringComparator::compareValues(txObject
* aVal1
, txObject
* aVal2
) {
72 nsString
& dval1
= *((StringValue
*)aVal1
)->mString
;
73 nsString
& dval2
= *((StringValue
*)aVal2
)->mString
;
76 MOZ_ASSERT_UNREACHABLE("No mCollator");
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
,
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();
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
;