VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/examples/xsltICUSort.c@ 9259

Last change on this file since 9259 was 7296, checked in by vboxsync, 17 years ago

Added libxslt-1.1.22 sources.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 8.3 KB
Line 
1/**
2 * xsltICUSort.c: module provided by Richard Jinks to provide a
3 * sort function replacement using ICU, it is not
4 * included in standard due to the size of the ICU
5 * library
6 *
7 * See http://mail.gnome.org/archives/xslt/2002-November/msg00093.html
8 * http://oss.software.ibm.com/icu/index.html
9 *
10 * Copyright Richard Jinks
11 */
12#define IN_LIBXSLT
13#include "libxslt.h"
14
15#include <libxml/parserInternals.h>
16
17#include "xslt.h"
18#include "xsltInternals.h"
19#include "xsltutils.h"
20#include "transform.h"
21#include "templates.h"
22
23#include <unicode/ucnv.h>
24#include <unicode/ustring.h>
25#include <unicode/utypes.h>
26#include <unicode/uloc.h>
27#include <unicode/ucol.h>
28
29/**
30 * xsltICUSortFunction:
31 * @ctxt: a XSLT process context
32 * @sorts: array of sort nodes
33 * @nbsorts: the number of sorts in the array
34 *
35 * reorder the current node list accordingly to the set of sorting
36 * requirement provided by the arry of nodes.
37 * uses the ICU library
38 */
39void
40xsltICUSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
41 int nbsorts) {
42 xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
43 xmlXPathObjectPtr *results = NULL, *res;
44 xmlNodeSetPtr list = NULL;
45 int descending, number, desc, numb;
46 int len = 0;
47 int i, j, incr;
48 int tst;
49 int depth;
50 xmlNodePtr node;
51 xmlXPathObjectPtr tmp;
52 xsltStylePreCompPtr comp;
53 int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
54
55 /* Start ICU change */
56 UCollator *coll = 0;
57 UConverter *conv;
58 UErrorCode status;
59 UChar *target,*target2;
60 int targetlen, target2len;
61 /* End ICU change */
62
63 if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
64 (nbsorts >= XSLT_MAX_SORT))
65 return;
66 if (sorts[0] == NULL)
67 return;
68 comp = sorts[0]->_private;
69 if (comp == NULL)
70 return;
71
72 list = ctxt->nodeList;
73 if ((list == NULL) || (list->nodeNr <= 1))
74 return; /* nothing to do */
75
76 for (j = 0; j < nbsorts; j++) {
77 comp = sorts[j]->_private;
78 tempstype[j] = 0;
79 if ((comp->stype == NULL) && (comp->has_stype != 0)) {
80 comp->stype =
81 xsltEvalAttrValueTemplate(ctxt, sorts[j],
82 (const xmlChar *) "data-type",
83 XSLT_NAMESPACE);
84 if (comp->stype != NULL) {
85 tempstype[j] = 1;
86 if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
87 comp->number = 0;
88 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
89 comp->number = 1;
90 else {
91 xsltTransformError(ctxt, NULL, sorts[j],
92 "xsltDoSortFunction: no support for data-type = %s\n",
93 comp->stype);
94 comp->number = 0; /* use default */
95 }
96 }
97 }
98 temporder[j] = 0;
99 if ((comp->order == NULL) && (comp->has_order != 0)) {
100 comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
101 (const xmlChar *) "order",
102 XSLT_NAMESPACE);
103 if (comp->order != NULL) {
104 temporder[j] = 1;
105 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
106 comp->descending = 0;
107 else if (xmlStrEqual(comp->order,
108 (const xmlChar *) "descending"))
109 comp->descending = 1;
110 else {
111 xsltTransformError(ctxt, NULL, sorts[j],
112 "xsltDoSortFunction: invalid value %s for order\n",
113 comp->order);
114 comp->descending = 0; /* use default */
115 }
116 }
117 }
118 }
119
120 len = list->nodeNr;
121
122 resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
123 for (i = 1;i < XSLT_MAX_SORT;i++)
124 resultsTab[i] = NULL;
125
126 results = resultsTab[0];
127
128 comp = sorts[0]->_private;
129 descending = comp->descending;
130 number = comp->number;
131 if (results == NULL)
132 return;
133
134 /* Start ICU change */
135 status = U_ZERO_ERROR;
136 conv = ucnv_open("UTF8", &status);
137 if(U_FAILURE(status)) {
138 xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening converter\n");
139 }
140 if(comp->has_lang)
141 coll = ucol_open(comp->lang, &status);
142 if(U_FAILURE(status) || !comp->has_lang) {
143 status = U_ZERO_ERROR;
144 coll = ucol_open("en", &status);
145 }
146 if(U_FAILURE(status)) {
147 xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error opening collator\n");
148 }
149 if(comp->lower_first)
150 ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_LOWER_FIRST,&status);
151 else
152 ucol_setAttribute(coll,UCOL_CASE_FIRST,UCOL_UPPER_FIRST,&status);
153 if(U_FAILURE(status)) {
154 xsltTransformError(ctxt, NULL, NULL, "xsltICUSortFunction: Error setting collator attribute\n");
155 }
156 /* End ICU change */
157
158 /* Shell's sort of node-set */
159 for (incr = len / 2; incr > 0; incr /= 2) {
160 for (i = incr; i < len; i++) {
161 j = i - incr;
162 if (results[i] == NULL)
163 continue;
164
165 while (j >= 0) {
166 if (results[j] == NULL)
167 tst = 1;
168 else {
169 if (number) {
170 if (results[j]->floatval == results[j + incr]->floatval)
171 tst = 0;
172 else if (results[j]->floatval >
173 results[j + incr]->floatval)
174 tst = 1;
175 else tst = -1;
176 } else {
177/* tst = xmlStrcmp(results[j]->stringval,
178 results[j + incr]->stringval); */
179 /* Start ICU change */
180 targetlen = xmlStrlen(results[j]->stringval) * 2;
181 target2len = xmlStrlen(results[j + incr]->stringval) * 2;
182 target = xmlMalloc(targetlen * sizeof(UChar));
183 target2 = xmlMalloc(target2len * sizeof(UChar));
184 targetlen = ucnv_toUChars(conv, target, targetlen, results[j]->stringval, -1, &status);
185 target2len = ucnv_toUChars(conv, target2, target2len, results[j+incr]->stringval, -1, &status);
186 tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2));
187 /* End ICU change */
188 }
189 if (descending)
190 tst = -tst;
191 }
192 if (tst == 0) {
193 /*
194 * Okay we need to use multi level sorts
195 */
196 depth = 1;
197 while (depth < nbsorts) {
198 if (sorts[depth] == NULL)
199 break;
200 comp = sorts[depth]->_private;
201 if (comp == NULL)
202 break;
203 desc = comp->descending;
204 numb = comp->number;
205
206 /*
207 * Compute the result of the next level for the
208 * full set, this might be optimized ... or not
209 */
210 if (resultsTab[depth] == NULL)
211 resultsTab[depth] = xsltComputeSortResult(ctxt,
212 sorts[depth]);
213 res = resultsTab[depth];
214 if (res == NULL)
215 break;
216 if (res[j] == NULL)
217 tst = 1;
218 else {
219 if (numb) {
220 if (res[j]->floatval == res[j + incr]->floatval)
221 tst = 0;
222 else if (res[j]->floatval >
223 res[j + incr]->floatval)
224 tst = 1;
225 else tst = -1;
226 } else {
227/* tst = xmlStrcmp(res[j]->stringval,
228 res[j + incr]->stringval); */
229 /* Start ICU change */
230 targetlen = xmlStrlen(res[j]->stringval) * 2;
231 target2len = xmlStrlen(res[j + incr]->stringval) * 2;
232 target = xmlMalloc(targetlen * sizeof(UChar));
233 target2 = xmlMalloc(target2len * sizeof(UChar));
234 targetlen = ucnv_toUChars(conv, target, targetlen, res[j]->stringval, -1, &status);
235 target2len = ucnv_toUChars(conv, target2, target2len, res[j+incr]->stringval, -1, &status);
236 tst = ucol_strcoll(coll, target, u_strlen(target), target2, u_strlen(target2));
237 /* End ICU change */
238 }
239 if (desc)
240 tst = -tst;
241 }
242 /*
243 * if we still can't differenciate at this level
244 * try one level deeper.
245 */
246 if (tst != 0)
247 break;
248 depth++;
249 }
250 }
251 if (tst == 0) {
252 tst = results[j]->index > results[j + incr]->index;
253 }
254 if (tst > 0) {
255 tmp = results[j];
256 results[j] = results[j + incr];
257 results[j + incr] = tmp;
258 node = list->nodeTab[j];
259 list->nodeTab[j] = list->nodeTab[j + incr];
260 list->nodeTab[j + incr] = node;
261 depth = 1;
262 while (depth < nbsorts) {
263 if (sorts[depth] == NULL)
264 break;
265 if (resultsTab[depth] == NULL)
266 break;
267 res = resultsTab[depth];
268 tmp = res[j];
269 res[j] = res[j + incr];
270 res[j + incr] = tmp;
271 depth++;
272 }
273 j -= incr;
274 } else
275 break;
276 }
277 }
278 }
279
280 /* Start ICU change */
281 ucol_close(coll);
282 ucnv_close(conv);
283 /* End ICU change */
284
285 for (j = 0; j < nbsorts; j++) {
286 comp = sorts[j]->_private;
287 if (tempstype[j] == 1) {
288 /* The data-type needs to be recomputed each time */
289 xmlFree(comp->stype);
290 comp->stype = NULL;
291 }
292 if (temporder[j] == 1) {
293 /* The order needs to be recomputed each time */
294 xmlFree(comp->order);
295 comp->order = NULL;
296 }
297 if (resultsTab[j] != NULL) {
298 for (i = 0;i < len;i++)
299 xmlXPathFreeObject(resultsTab[j][i]);
300 xmlFree(resultsTab[j]);
301 }
302 }
303}
304
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette