Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/. */
5 :
6 : #include "mozilla/FloatingPoint.h"
7 :
8 : #include "txXPathResultComparator.h"
9 : #include "txExpr.h"
10 : #include "txCore.h"
11 : #include "nsCollationCID.h"
12 : #include "nsIServiceManager.h"
13 :
14 : #define kAscending (1<<0)
15 : #define kUpperFirst (1<<1)
16 :
17 0 : txResultStringComparator::txResultStringComparator(bool aAscending,
18 : bool aUpperFirst,
19 0 : const nsString& aLanguage)
20 : {
21 0 : mSorting = 0;
22 0 : if (aAscending)
23 0 : mSorting |= kAscending;
24 0 : if (aUpperFirst)
25 0 : mSorting |= kUpperFirst;
26 0 : nsresult rv = init(aLanguage);
27 0 : if (NS_FAILED(rv))
28 0 : NS_ERROR("Failed to initialize txResultStringComparator");
29 0 : }
30 :
31 0 : nsresult txResultStringComparator::init(const nsString& aLanguage)
32 : {
33 : nsresult rv;
34 :
35 : nsCOMPtr<nsICollationFactory> colFactory =
36 0 : do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID, &rv);
37 0 : NS_ENSURE_SUCCESS(rv, rv);
38 :
39 0 : if (aLanguage.IsEmpty()) {
40 0 : rv = colFactory->CreateCollation(getter_AddRefs(mCollation));
41 : } else {
42 0 : rv = colFactory->CreateCollationForLocale(NS_ConvertUTF16toUTF8(aLanguage), getter_AddRefs(mCollation));
43 : }
44 :
45 0 : NS_ENSURE_SUCCESS(rv, rv);
46 :
47 0 : return NS_OK;
48 : }
49 :
50 : nsresult
51 0 : txResultStringComparator::createSortableValue(Expr *aExpr,
52 : txIEvalContext *aContext,
53 : txObject *&aResult)
54 : {
55 0 : nsAutoPtr<StringValue> val(new StringValue);
56 0 : if (!val) {
57 0 : return NS_ERROR_OUT_OF_MEMORY;
58 : }
59 :
60 0 : if (!mCollation)
61 0 : return NS_ERROR_FAILURE;
62 :
63 0 : val->mCaseKey = new nsString;
64 0 : nsString& nsCaseKey = *(nsString *)val->mCaseKey;
65 0 : nsresult rv = aExpr->evaluateToString(aContext, nsCaseKey);
66 0 : NS_ENSURE_SUCCESS(rv, rv);
67 :
68 0 : if (nsCaseKey.IsEmpty()) {
69 0 : aResult = val.forget();
70 :
71 0 : return NS_OK;
72 : }
73 :
74 0 : rv = mCollation->AllocateRawSortKey(nsICollation::kCollationCaseInSensitive,
75 0 : nsCaseKey, &val->mKey, &val->mLength);
76 0 : NS_ENSURE_SUCCESS(rv, rv);
77 :
78 0 : aResult = val.forget();
79 :
80 0 : return NS_OK;
81 : }
82 :
83 0 : int txResultStringComparator::compareValues(txObject* aVal1, txObject* aVal2)
84 : {
85 0 : StringValue* strval1 = (StringValue*)aVal1;
86 0 : StringValue* strval2 = (StringValue*)aVal2;
87 :
88 0 : if (!mCollation)
89 0 : return -1;
90 :
91 0 : if (strval1->mLength == 0) {
92 0 : if (strval2->mLength == 0)
93 0 : return 0;
94 0 : return ((mSorting & kAscending) ? -1 : 1);
95 : }
96 :
97 0 : if (strval2->mLength == 0)
98 0 : return ((mSorting & kAscending) ? 1 : -1);
99 :
100 : nsresult rv;
101 0 : int32_t result = -1;
102 0 : rv = mCollation->CompareRawSortKey(strval1->mKey, strval1->mLength,
103 0 : strval2->mKey, strval2->mLength,
104 0 : &result);
105 0 : if (NS_FAILED(rv)) {
106 : // XXX ErrorReport
107 0 : return -1;
108 : }
109 :
110 0 : if (result != 0)
111 0 : return ((mSorting & kAscending) ? 1 : -1) * result;
112 :
113 0 : if ((strval1->mCaseLength == 0) && (strval1->mLength != 0)) {
114 0 : nsString* caseString = (nsString *)strval1->mCaseKey;
115 0 : rv = mCollation->AllocateRawSortKey(nsICollation::kCollationCaseSensitive,
116 : *caseString,
117 0 : (uint8_t**)&strval1->mCaseKey,
118 0 : &strval1->mCaseLength);
119 0 : if (NS_FAILED(rv)) {
120 : // XXX ErrorReport
121 0 : strval1->mCaseKey = caseString;
122 0 : strval1->mCaseLength = 0;
123 0 : return -1;
124 : }
125 0 : delete caseString;
126 : }
127 0 : if ((strval2->mCaseLength == 0) && (strval2->mLength != 0)) {
128 0 : nsString* caseString = (nsString *)strval2->mCaseKey;
129 0 : rv = mCollation->AllocateRawSortKey(nsICollation::kCollationCaseSensitive,
130 : *caseString,
131 0 : (uint8_t**)&strval2->mCaseKey,
132 0 : &strval2->mCaseLength);
133 0 : if (NS_FAILED(rv)) {
134 : // XXX ErrorReport
135 0 : strval2->mCaseKey = caseString;
136 0 : strval2->mCaseLength = 0;
137 0 : return -1;
138 : }
139 0 : delete caseString;
140 : }
141 0 : rv = mCollation->CompareRawSortKey((uint8_t*)strval1->mCaseKey, strval1->mCaseLength,
142 0 : (uint8_t*)strval2->mCaseKey, strval2->mCaseLength,
143 0 : &result);
144 0 : if (NS_FAILED(rv)) {
145 : // XXX ErrorReport
146 0 : return -1;
147 : }
148 :
149 0 : return ((mSorting & kAscending) ? 1 : -1) *
150 0 : ((mSorting & kUpperFirst) ? -1 : 1) * result;
151 : }
152 :
153 0 : txResultStringComparator::StringValue::StringValue() : mKey(0),
154 : mCaseKey(0),
155 : mLength(0),
156 0 : mCaseLength(0)
157 : {
158 0 : }
159 :
160 0 : txResultStringComparator::StringValue::~StringValue()
161 : {
162 0 : free(mKey);
163 0 : if (mCaseLength > 0)
164 0 : free(mCaseKey);
165 : else
166 0 : delete (nsString*)mCaseKey;
167 0 : }
168 :
169 0 : txResultNumberComparator::txResultNumberComparator(bool aAscending)
170 : {
171 0 : mAscending = aAscending ? 1 : -1;
172 0 : }
173 :
174 : nsresult
175 0 : txResultNumberComparator::createSortableValue(Expr *aExpr,
176 : txIEvalContext *aContext,
177 : txObject *&aResult)
178 : {
179 0 : nsAutoPtr<NumberValue> numval(new NumberValue);
180 0 : if (!numval) {
181 0 : return NS_ERROR_OUT_OF_MEMORY;
182 : }
183 :
184 0 : RefPtr<txAExprResult> exprRes;
185 0 : nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprRes));
186 0 : NS_ENSURE_SUCCESS(rv, rv);
187 :
188 0 : numval->mVal = exprRes->numberValue();
189 :
190 0 : aResult = numval.forget();
191 :
192 0 : return NS_OK;
193 : }
194 :
195 0 : int txResultNumberComparator::compareValues(txObject* aVal1, txObject* aVal2)
196 : {
197 0 : double dval1 = ((NumberValue*)aVal1)->mVal;
198 0 : double dval2 = ((NumberValue*)aVal2)->mVal;
199 :
200 0 : if (mozilla::IsNaN(dval1))
201 0 : return mozilla::IsNaN(dval2) ? 0 : -mAscending;
202 :
203 0 : if (mozilla::IsNaN(dval2))
204 0 : return mAscending;
205 :
206 0 : if (dval1 == dval2)
207 0 : return 0;
208 :
209 0 : return (dval1 < dval2) ? -mAscending : mAscending;
210 : }
|