2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
12 * The Original Code is the Sablotron XSLT Processor.
14 * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16 * Ginger Alliance Ltd. All Rights Reserved.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU General Public License Version 2 or later (the
22 * "GPL"), in which case the provisions of the GPL are applicable
23 * instead of those above. If you wish to allow use of your
24 * version of this file only under the terms of the GPL and not to
25 * allow others to use your version of this file under the MPL,
26 * indicate your decision by deleting the provisions above and
27 * replace them with the notice and other provisions required by
28 * the GPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under either the MPL or the
33 /*****************************************************************
37 *****************************************************************/
44 #include "domprovider.h"
45 #include "guard.h" // GP: clean
47 /*****************************************************************
49 primarily for different language names in Windows setlocale
50 (unix setlocale respects ISO 639 which is also the standard
51 for language codes in XML docs)
52 SO FAR FOR TESTING PURPOSES
54 each entry contains 2 strings with space-separated codes
55 - first with the ISO codes (may appear in XML)
56 - second with the setlocale-specific codes (needn't be ISO outside unix)
57 *****************************************************************/
62 *namesISO, *namesLocale;
65 LangAlias langAliases[] =
71 {"cze ces cs cs_CZ", "cs_CZ czech"},
72 {"sk slk slo sk_SK", "sk_SK slovak"},
76 /*****************************************************************
78 *****************************************************************/
82 SList<NodeHandle>(LIST_SIZE_LARGE)
90 // GP: added method to kill values
97 void CList::incRefCount()
102 int CList::decRefCount()
107 // compareWithoutDocOrd
108 // assumes that the 'values' entries have been created
109 // compares 2 vertices based on just the values, not their relative document order
111 Bool CList::tagChanged(int i, int j)
113 return tags[i] != tags[j];
116 int CList::compareWithoutDocOrd(int i, int j)
118 assert(sortDefs && currLevel < sortDefs -> number());
119 assert(i < values.number() && j < values.number());
121 SortDef *def = (*sortDefs)[currLevel];
122 // *** use case-order and lang from def!!!
128 result = wcscmp__((char*)values[i], (char*)values[j]);
132 result = strcmp((char*)values[i], (char*)values[j]);
138 n1 = (char*)values[i];
139 n2 = (char*)values[j];
143 result = (n2 < n1) ? 1 : 0;
145 return def -> ascend ? result : -result;
149 // compare assumes that the 'values' entries have been created
150 int CList::compare(int i, int j, void *data)
154 int result = compareWithoutDocOrd(i, j);
158 // sort in document order
159 NodeHandle v1 = block[i], v2 = block[j];
161 return ((DOMProvider*)data) -> compareNodes(v1, v2);
164 Bool hasWord(const char *sentence, const char *w)
169 for (p = sentence; *p; p += len + strspn(p, " "))
171 currWord.nset(p, len = strcspn(p, " "));
172 if (currWord.eqNoCase(w)) return TRUE;
177 char* setLang(const Str& src)
183 if (NULL != (result = setlocale(LC_COLLATE, src)))
186 LangAlias *a = langAliases;
187 while(a -> namesISO && !hasWord(a -> namesISO, src)) a++;
190 for (p = a -> namesLocale; *p; p += len + strspn(p, " "))
192 dest.nset(p, len = strcspn(p, " "));
193 if (NULL != (result = setlocale(LC_COLLATE, dest)))
201 void __dump(CList& lst, int idx1, int idx2)
203 printf("\n--- DUMP - BEGIN (%d, %d) ---\n", idx1, idx2);
204 for (int i = 0; i < lst.number(); i++)
206 if (isElement(lst[i]))
208 Element* e = toE(lst[i]);
209 for (int j = 0; j < e -> atts.number(); j++)
211 printf("%2s", (char*)((Attribute*)e -> atts[j]) -> cont);
216 printf("--- DUMP - END ---\n\n");
219 eFlag CList::sort(Sit S, XSLElement *caller, Context *ctxt, SortDefList* sortDefs_ /* = NULL */)
221 // GP: on error, locale is reset
222 // checked that all callers destroy the context on error
224 assert(caller || !sortDefs_);
226 sortDefs = sortDefs_;
229 if (!setLang((*sortDefs)[0] -> lang))
231 Warn1(S, W1_LANG, (*sortDefs)[0] -> lang);
232 setlocale(LC_COLLATE, "C");
234 // this is to reset the locale if there's an error
235 E_DO( makeValues(S, 0, number() - 1, 0, caller, ctxt),
236 setlocale(LC_COLLATE, "C") );
239 SList<NodeHandle>::sort(0, number() - 1, &(S.dom()));
240 for (int i = 1; sortDefs && (i < sortDefs -> number()); i++)
242 if (!setLang((*sortDefs)[i] -> lang))
244 Warn1(S, W1_LANG, (*sortDefs)[i] -> lang);
245 setlocale(LC_COLLATE, "C");
249 for (int j = 1; j <= number(); j++)
250 if (j == number() || compareWithoutDocOrd(j0,j) ||
256 E_DO( makeValues(S, j0, j-1, i, caller, ctxt),
257 setlocale(LC_COLLATE, "C"));
258 // printf("Sorting %d:%d to %d\n",i,j0,j-1);
259 SList<NodeHandle>::sort(j0, j-1, &(S.dom()));
260 //set tags for the next level
262 for (int aux = j0; aux < j; aux++) tags[aux] = currTag;
263 // reset currLevel for next compareWithoutDocOrd()
271 // *** unset the temp locale as necessary
272 setlocale(LC_ALL, "C");
273 values.freeall(TRUE);
276 // reset the current element of parent context
277 ctxt -> setPosition(0);
281 void CList::swap(int i, int j)
283 SList<NodeHandle>::swap(i, j);
291 eFlag CList::makeValues(Sit S, int from, int to, int level,
292 XSLElement *caller, Context *ctxt)
296 if (!sortDefs) return OK;
298 // we may assume that the node handles are actually pointers now
299 assert(level < sortDefs -> number());
300 SortDef *def = (*sortDefs)[level];
305 Expression *e, result(*caller, EXF_ATOM);
306 for (int i = from; i <= to; i++)
308 ctxt -> setPosition(i);
313 E( toPhysical((*this)[i]) -> value(S, d, ctxt) );
316 # if defined(SAB_WCS_COLLATE)
317 strg.assign( utf8xfrm(d) );
320 strg.assign( d.cloneData() );
324 strg.assign(d.cloneData() );
328 E( e -> eval(S, result, ctxt) );
332 # if defined(SAB_WCS_COLLATE)
334 E( result.tostring(S, temp) );
335 strg.assign( utf8xfrm(temp) );
339 E(result.tostring(S,aux));
340 strg.assign( aux.cloneData() );
345 E(result.tostring(S, aux));
346 strg.assign( aux.cloneData() );
351 values.append(strg.keep());
356 cdeleteArr(values[i]);
357 values[i] = strg.keep();
363 void CList::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2)
365 S.message(type, code, arg1, arg2);
369 /*****************************************************************
371 C o n t e x t methods
373 ******************************************************************/
375 Context::Context(NodeHandle current, int isForKey_ /* = FALSE */)
377 isForKey = isForKey_;
378 array = isForKey? new KList : new CList;
379 currentNode = current;
388 if (!array -> decRefCount())
392 int Context::getPosition() const
394 return position + virtualPosition;
397 int Context::getSize() const
399 if (virtualSize != -1)
402 return array -> number();
405 NodeHandle Context::current() const
408 return (*array)[position];
413 NodeHandle Context::getCurrentNode() const
424 void Context::setCurrentNode(NodeHandle v)
429 void Context::reset()
431 if (!array -> number())
437 Bool Context::isFinished() const
439 return (Bool) !((position >= 0) && (position < array -> number()));
442 Bool Context::isVoid() const
444 return (Bool) !(array -> number());
447 NodeHandle Context::shift()
449 if ((position >= 0) && (position < array -> number() - 1))
450 return (*this)[++position];
455 void Context::set(NodeHandle v)
461 void Context::setVirtual(NodeHandle v, int virtualPosition_, int virtualSize_)
463 assert(!array -> number() && "setVirtual() on nonvoid context");
465 virtualSize = virtualSize_;
466 virtualPosition = virtualPosition_;
470 NodeHandle Context::operator[] (int n) const
475 void Context::deppendall()
477 if (!array -> decRefCount())
479 array = isForKey? new KList : new CList;
483 void Context::append(NodeHandle v)
489 void Context::deppend()
492 if (position >= array -> number())
493 position = array -> number() - 1;
496 Context* Context::copy()
498 Context *newc = new Context(currentNode);
499 delete NZ(newc -> array);
500 newc -> array = array;
501 newc -> virtualPosition = virtualPosition;
502 newc -> virtualSize = virtualSize;
503 array -> incRefCount();
508 void Context::swap(int i, int j)
513 Context* Context::swallow(Sit S, Context *other)
515 Context *result = new Context(currentNode); // GP: OK since no E()
517 iLimit = array -> number(), jLimit = other -> array -> number();
519 while ((i < iLimit) && (j < jLimit))
523 switch(S.dom().compareNodes(v, w))
541 result -> append((*array)[i++]);
543 result -> append((*(other -> array))[j++]);
545 other -> deppendall();
549 Bool Context::contains(NodeHandle v) const
552 for (i = 0; i < array -> number(); i++)
554 if (v == (*array)[i])
560 void Context::uniquize()
563 for (i = array -> number() - 2; i >= 0; i--)
564 if ((*array)[i] == (*array)[i+1])
568 CList* Context::getArrayForDOM()
573 KList* Context::getKeyArray()
576 return cast(KList*, array);