1 /*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "stdafx.h"
17
18 #include <vector>
19
20 #include "common/shared_types.h"
21
22 #include "diagnostics/assert.h"
23 #include "diagnostics/util_macros.h"
24 #include "diagnostics/xquery_diagnostics.h"
25 #include "zorbatypes/zorbatypes_decl.h"
26
27 #include "system/globalenv.h"
28
29 #include "util/tracer.h"
30 #include "util/utf8_string.h"
31
32 #include "types/casting.h"
33 #include "types/typeconstants.h"
34 #include "types/typeops.h"
35
36 #include "context/static_context.h"
37
38 #include "compiler/api/compilercb.h"
39
40 #include "runtime/numerics/numerics.h"
41 #include "runtime/visitors/planiter_visitor.h"
42 #include "runtime/core/arithmetic_impl.h"
43
44 #include "store/api/item_factory.h"
45 #include "store/api/item.h"
46
47 namespace zorba
48 {
49 //6.4.1 fn:abs
50 bool
nextImpl(store::Item_t & result,PlanState & planState) const51 AbsIterator::nextImpl(store::Item_t& result, PlanState& planState) const
52 {
53 store::Item_t item;
54 xqtref_t type;
55
56 const TypeManager* tm = theSctx->get_typemanager();
57
58 const RootTypeManager& rtm = GENV_TYPESYSTEM;
59
60 PlanIteratorState* state;
61 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
62
63 if (consumeNext(result, theChildren[0].getp(), planState))
64 {
65 assert(result->isAtomic());
66
67 type = tm->create_value_type(result);
68
69 if (TypeOps::is_subtype(tm, *type, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
70 {
71 GenericCast::castToAtomic(result, result, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
72 type = tm->create_value_type(result);
73 }
74
75 if (TypeOps::is_subtype(tm, *type, *rtm.DOUBLE_TYPE_ONE))
76 {
77 if (result->getDoubleValue().isPos() || result->getDoubleValue().isPosZero())
78 {
79 if ( !TypeOps::is_equal(tm, *type, *rtm.DOUBLE_TYPE_ONE))
80 GENV_ITEMFACTORY->createDouble (result, result->getDoubleValue());
81 }
82 else
83 {
84 GENV_ITEMFACTORY->createDouble(result, -result->getDoubleValue());
85 }
86 }
87 else if (TypeOps::is_subtype(tm, *type, *rtm.FLOAT_TYPE_ONE))
88 {
89 if ( result->getFloatValue().isPos() || result->getFloatValue().isPosZero())
90 {
91 if ( !TypeOps::is_equal(tm, *type, *rtm.FLOAT_TYPE_ONE))
92 GENV_ITEMFACTORY->createFloat (result, result->getFloatValue());
93 }
94 else
95 {
96 GENV_ITEMFACTORY->createFloat(result, -result->getFloatValue());
97 }
98 }
99 else if (TypeOps::is_subtype(tm, *type, *rtm.INTEGER_TYPE_ONE))
100 {
101 if (result->getIntegerValue() >= xs_decimal::zero())
102 {
103 if ( !TypeOps::is_equal(tm, *type, *rtm.INTEGER_TYPE_ONE))
104 GENV_ITEMFACTORY->createInteger(result, result->getIntegerValue());
105 }
106 else
107 {
108 GENV_ITEMFACTORY->createInteger(result, -result->getIntegerValue());
109 }
110 }
111 else if (TypeOps::is_subtype(tm, *type, *rtm.DECIMAL_TYPE_ONE))
112 {
113 if ( result->getDecimalValue() >= xs_decimal::zero())
114 {
115 if ( !TypeOps::is_equal(tm, *type, *rtm.DECIMAL_TYPE_ONE))
116 GENV_ITEMFACTORY->createDecimal(result, result->getDecimalValue());
117 }
118 else
119 {
120 GENV_ITEMFACTORY->createDecimal (result, -result->getDecimalValue());
121 }
122 }
123 else
124 {
125 RAISE_ERROR(err::XPTY0004, loc,
126 ERROR_PARAMS(ZED(BadTypeFor_23), type, "fn:abs" ));
127 }
128
129 if ( consumeNext(item, theChildren[0].getp(), planState ))
130 {
131 RAISE_ERROR(err::XPTY0004, loc,
132 ERROR_PARAMS(ZED(NoSeqForFnOp_2), "fn:abs"));
133 }
134
135 STACK_PUSH(true, state);
136 }
137 STACK_END(state);
138 }
139
140 //6.4.2 fn:ceiling
141 bool
nextImpl(store::Item_t & result,PlanState & planState) const142 CeilingIterator::nextImpl(store::Item_t& result, PlanState& planState) const
143 {
144 store::Item_t item;
145 xqtref_t type;
146
147 const TypeManager* tm = theSctx->get_typemanager();
148 const RootTypeManager& rtm = GENV_TYPESYSTEM;
149
150 PlanIteratorState* state;
151 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
152
153 if (consumeNext(result, theChildren[0].getp(), planState))
154 {
155 //get the value and the type of the item
156 assert(result->isAtomic());
157
158 type = tm->create_value_type(result);
159
160 //Parameters of type xs:untypedAtomic are always promoted to xs:double
161 if ( TypeOps::is_subtype(tm, *type, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
162 {
163 GenericCast::castToAtomic(result, result, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
164 type = tm->create_value_type(result);
165 }
166
167 //item type is subtype of DOUBLE
168 if ( TypeOps::is_subtype(tm, *type, *rtm.DOUBLE_TYPE_ONE))
169 GENV_ITEMFACTORY->createDouble(result, result->getDoubleValue().ceil());
170
171 //item type is subtype of FLOAT
172 else if ( TypeOps::is_subtype(tm, *type, *rtm.FLOAT_TYPE_ONE))
173 GENV_ITEMFACTORY->createFloat(result, result->getFloatValue().ceil());
174
175 //item type is subtype of INTEGER
176 else if(TypeOps::is_subtype(tm, *type, *rtm.INTEGER_TYPE_ONE))
177 { /* do nothing */ }
178
179 //item type is subtype of DECIMAL
180 else if (TypeOps::is_subtype(tm, *type, *rtm.DECIMAL_TYPE_ONE))
181 GENV_ITEMFACTORY->createDecimal(result, result->getDecimalValue().ceil());
182
183 else
184 {
185 RAISE_ERROR(err::XPTY0004, loc,
186 ERROR_PARAMS(ZED(BadTypeFor_23), type, "fn:ceiling" ));
187 }
188
189 if ( consumeNext(item, theChildren[0].getp(), planState ))
190 {
191 RAISE_ERROR(err::XPTY0004, loc,
192 ERROR_PARAMS(ZED(NoSeqForFnOp_2), "fn:ceiling"));
193 }
194 STACK_PUSH(true, state);
195 }
196 STACK_END(state);
197 }
198
199 //6.4.3 fn:floor
200 bool
nextImpl(store::Item_t & result,PlanState & planState) const201 FloorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
202 {
203 store::Item_t item;
204 xqtref_t type;
205
206 const TypeManager* tm = theSctx->get_typemanager();
207 const RootTypeManager& rtm = GENV_TYPESYSTEM;
208
209 PlanIteratorState* state;
210 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
211
212 if (consumeNext(result, theChildren[0].getp(), planState))
213 {
214 //get the value and the type of the item
215 assert(result->isAtomic());
216
217 type = tm->create_value_type(result);
218
219 //Parameters of type xs:untypedAtomic are always promoted to xs:double
220 if (TypeOps::is_subtype(tm, *type, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
221 {
222 GenericCast::castToAtomic(result, result, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
223 type = tm->create_value_type(result);
224 }
225
226 //item type is subtype of DOUBLE
227 if (TypeOps::is_subtype(tm, *type, *rtm.DOUBLE_TYPE_ONE))
228 GENV_ITEMFACTORY->createDouble(result, result->getDoubleValue().floor());
229
230 //item type is subtype of FLOAT
231 else if (TypeOps::is_subtype(tm, *type, *rtm.FLOAT_TYPE_ONE))
232 GENV_ITEMFACTORY->createFloat(result, result->getFloatValue().floor());
233
234 //item type is subtype of INTEGER
235 else if(TypeOps::is_subtype(tm, *type, *rtm.INTEGER_TYPE_ONE))
236 { /* do nothing */ }
237
238 //item type is subtype of DECIMAL
239 else if (TypeOps::is_subtype(tm, *type, *rtm.DECIMAL_TYPE_ONE))
240 GENV_ITEMFACTORY->createDecimal(result, result->getDecimalValue().floor());
241
242 else
243 {
244 RAISE_ERROR(err::XPTY0004, loc,
245 ERROR_PARAMS(ZED(BadTypeFor_23), type, "fn:floor"));
246 }
247
248 if ( consumeNext(item, theChildren[0].getp(), planState ) )
249 {
250 RAISE_ERROR(err::XPTY0004, loc,
251 ERROR_PARAMS(ZED(NoSeqForFnOp_2), "fn:floor" ));
252 }
253 STACK_PUSH (true, state );
254 }
255 STACK_END (state);
256 }
257
258 bool
nextImpl(store::Item_t & result,PlanState & planState) const259 RoundIterator::nextImpl(store::Item_t& result, PlanState& planState) const
260 {
261 store::Item_t item;
262 store::Item_t res;
263 xqtref_t type;
264 store::Item_t precision;
265 Integer precision_integer(0);
266
267 const TypeManager* tm = theSctx->get_typemanager();
268 const RootTypeManager& rtm = GENV_TYPESYSTEM;
269
270 PlanIteratorState* state;
271 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
272
273 if (consumeNext(result, theChildren[0].getp(), planState))
274 {
275 if (theChildren.size() == 2)
276 {
277 consumeNext(precision, theChildren[1].getp(), planState);
278 assert(precision->isAtomic());
279
280 precision_integer = precision->getIntegerValue();
281 }
282
283 //get the value and the type of the item
284 assert(result->isAtomic());
285
286 type = tm->create_value_type(result);
287
288 //Parameters of type xs:untypedAtomic are always promoted to xs:double
289 if ( TypeOps::is_subtype(tm, *type, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
290 {
291 GenericCast::castToAtomic(result, result, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
292 type = tm->create_value_type(result);
293 }
294
295 //item type is subtype of DOUBLE
296 if ( TypeOps::is_subtype(tm, *type, *rtm.DOUBLE_TYPE_ONE))
297 GENV_ITEMFACTORY->createDouble(result, result->getDoubleValue().round(precision_integer));
298
299 //item type is subtype of FLOAT
300 else if ( TypeOps::is_subtype(tm, *type, *rtm.FLOAT_TYPE_ONE))
301 GENV_ITEMFACTORY->createFloat(result, result->getFloatValue().round(precision_integer));
302
303 //item type is subtype of INTEGER
304 else if(TypeOps::is_subtype(tm, *type, *rtm.INTEGER_TYPE_ONE))
305 {
306 if(precision_integer < Integer::zero())
307 GENV_ITEMFACTORY->createInteger(result, result->getIntegerValue().round(precision_integer));
308 }
309
310 //item type is subtype of DECIMAL
311 else if (TypeOps::is_subtype(tm, *type, *rtm.DECIMAL_TYPE_ONE))
312 GENV_ITEMFACTORY->createDecimal(result, result->getDecimalValue().round(precision_integer));
313
314 else
315 {
316 RAISE_ERROR(err::XPTY0004, loc,
317 ERROR_PARAMS(ZED(BadTypeFor_23), type, "fn:round"));
318 }
319
320 if ( consumeNext(item, theChildren[0].getp(), planState ))
321 {
322 RAISE_ERROR(err::XPTY0004, loc,
323 ERROR_PARAMS(ZED(NoSeqForFnOp_2), "fn:round" ));
324 }
325 STACK_PUSH (true, state );
326 }
327 STACK_END (state);
328 }
329
330 //6.4.5 fn:round-half-to-even
331 bool
nextImpl(store::Item_t & result,PlanState & planState) const332 RoundHalfToEvenIterator::nextImpl(store::Item_t& result, PlanState& planState) const
333 {
334 store::Item_t item;
335 store::Item_t itemPrec;
336 store::Item_t res;
337 xqtref_t type;
338 Integer precision(0);
339
340 const TypeManager* tm = theSctx->get_typemanager();
341 const RootTypeManager& rtm = GENV_TYPESYSTEM;
342
343 PlanIteratorState* state;
344 DEFAULT_STACK_INIT ( PlanIteratorState, state, planState );
345
346 if (consumeNext(result, theChildren [0].getp(), planState ))
347 {
348 if (theChildren.size() == 2)
349 {
350 consumeNext(itemPrec, theChildren[1].getp(), planState);
351 assert(itemPrec->isAtomic());
352
353 precision = itemPrec->getIntegerValue();
354 }
355
356 //get the value and the type of the item
357 assert(result->isAtomic());
358
359 type = tm->create_value_type(result);
360
361 //Parameters of type xs:untypedAtomic are always promoted to xs:double
362 if ( TypeOps::is_subtype(tm, *type, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
363 {
364 GenericCast::castToAtomic(result, result, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
365 type = tm->create_value_type (result);
366 }
367
368 //item type is subtype of DOUBLE
369 if ( TypeOps::is_subtype(tm, *type, *rtm.DOUBLE_TYPE_ONE))
370 GENV_ITEMFACTORY->createDouble(result, result->getDoubleValue().roundHalfToEven(precision));
371
372 //item type is subtype of FLOAT
373 else if ( TypeOps::is_subtype(tm, *type, *rtm.FLOAT_TYPE_ONE))
374 GENV_ITEMFACTORY->createFloat(result, result->getFloatValue().roundHalfToEven(precision));
375
376 //item type is subtype of INTEGER
377 else if(TypeOps::is_subtype(tm, *type, *rtm.INTEGER_TYPE_ONE))
378 { /* do nothing */ }
379 //item type is subtype of DECIMAL
380 else if (TypeOps::is_subtype (tm, *type, *rtm.DECIMAL_TYPE_ONE))
381 GENV_ITEMFACTORY->createDecimal(result, result->getDecimalValue().roundHalfToEven(precision));
382
383 else
384 {
385 RAISE_ERROR(err::XPTY0004, loc,
386 ERROR_PARAMS(ZED(BadTypeFor_23), type, "fn:round-half-to-even"));
387 }
388
389 if ( consumeNext(item, theChildren [0].getp(), planState ))
390 {
391 RAISE_ERROR(err::XPTY0004, loc,
392 ERROR_PARAMS(ZED(NoSeqForFnOp_2), "fn:round-half-to-even"));
393 }
394 STACK_PUSH ( true, state );
395 }
396 STACK_END (state);
397 }
398
399 //XQuery 3.0 functions
400 /*******************************************************************************
401
402 ********************************************************************************/
403 static const char* decimal_separator_param = "decimal-separator";
404 static const char* grouping_separator_param = "grouping-separator";
405 static const char* infinity_param = "infinity";
406 static const char* minus_sign_param = "minus-sign";
407 static const char* nan_param = "NaN";
408 static const char* percent_param = "percent";
409 static const char* per_mille_param = "per-mille";
410 static const char* zero_digit_param = "zero-digit";
411 static const char* digit_param = "digit";
412 static const char* pattern_separator_param = "pattern-separator";
413
414
415 class FormatNumberInfo
416 {
417 public:
418 QueryLoc loc;
419 // Separators
420 zstring decimal_separator;
421 zstring grouping_separator;
422 zstring percent;
423 zstring per_mille;
424 zstring zero_digit;
425 zstring digit_sign;
426 zstring pattern_separator;
427 zstring infinity;
428 zstring NaN;
429 zstring minus;
430
431 zstring pictureString; // The original picture string, used for debugging and error reporting
432
433 class PartInfo
434 {
435 public:
436 zstring str;
437 std::vector<int> grouping_pos;
438 int N;
439 int minimum_size;
440 int maximum_size;
PartInfo()441 PartInfo() : N(-1), minimum_size(0), maximum_size(0) {};
442 };
443
444 class SubPictureInfo
445 {
446 public:
447 zstring str;
448 zstring prefix;
449 zstring suffix;
450 PartInfo integer_part;
451 PartInfo fractional_part;
SubPictureInfo()452 SubPictureInfo() { }
453 } pos_subpicture, neg_subpicture;
454
FormatNumberInfo()455 FormatNumberInfo() :
456 decimal_separator( "." ),
457 grouping_separator( "," ),
458 percent( "%" ),
459 zero_digit( "0" ),
460 digit_sign( "#" ),
461 pattern_separator( ";" ),
462 infinity( "Infinity" ),
463 NaN( "NaN" ),
464 minus( "-" )
465 {
466 utf8_string<zstring> u_per_mille( per_mille );
467 u_per_mille = (unicode::code_point)0x2030;
468 }
469
readFormat(const DecimalFormat_t & df_t)470 void readFormat(const DecimalFormat_t& df_t)
471 {
472 if (df_t.isNull())
473 return;
474
475 const DecimalFormat::param_vector_type* params = df_t->getParamVector();
476
477 for ( DecimalFormat::param_vector_type::const_iterator it = params->begin(); it != params->end(); it++)
478 {
479 if (it->first == decimal_separator_param)
480 decimal_separator = it->second.c_str();
481 else if (it->first == grouping_separator_param)
482 grouping_separator = it->second.c_str();
483 else if (it->first == infinity_param)
484 infinity = it->second.c_str();
485 else if (it->first == minus_sign_param)
486 minus = it->second.c_str();
487 else if (it->first == nan_param)
488 NaN = it->second.c_str();
489 else if (it->first == percent_param)
490 percent = it->second.c_str();
491 else if (it->first == per_mille_param)
492 per_mille = it->second.c_str();
493 else if (it->first == zero_digit_param)
494 zero_digit = it->second.c_str();
495 else if (it->first == digit_param)
496 digit_sign = it->second.c_str();
497 else if (it->first == pattern_separator_param)
498 pattern_separator = it->second.c_str();
499 }
500 }
501 };
502
503
504 // returns an error if there are two or more instances of the given pattern in the string
errorIfTwoOrMore(zstring const & part,const char * sep,FormatNumberInfo & info)505 static void errorIfTwoOrMore(zstring const& part, const char* sep, FormatNumberInfo& info)
506 {
507 zstring::size_type const pos = part.find(sep);
508
509 if (pos != zstring::npos)
510 {
511 if (part.find(sep, strlen(sep), pos+1) != zstring::npos)
512 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberDuplicates), sep), ERROR_LOC(info.loc));
513 }
514 }
515
516
parsePart(FormatNumberInfo & info,FormatNumberInfo::PartInfo & part,bool fractional=false)517 static void parsePart(
518 FormatNumberInfo& info,
519 FormatNumberInfo::PartInfo& part,
520 bool fractional = false)
521 {
522 zstring& str = part.str;
523 if (str.empty())
524 return;
525
526 errorIfTwoOrMore(str, info.percent.c_str(), info);
527 errorIfTwoOrMore(str, info.per_mille.c_str(), info);
528
529 if (str.find(info.percent.c_str()) != zstring::npos &&
530 str.find(info.per_mille.c_str()) != zstring::npos)
531 {
532 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberPercentPermille)), ERROR_LOC(info.loc));
533 }
534
535 if (str.find(info.digit_sign.c_str()) == zstring::npos &&
536 str.find(info.zero_digit.c_str()) == zstring::npos)
537 {
538 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberAtLeastOneOptionalOrDecimal)), ERROR_LOC(info.loc));
539 }
540
541 // get grouping separators
542 int digit_signs = 0;
543 int zero_signs = 0;
544 int start = fractional? 0 : (int)str.size()-1;
545 int end = fractional? (int)str.size() : -1;
546 int delta = fractional? 1 : -1;
547 int first_digit_sign = -1;
548 int last_zero_sign = -1;
549 while (start != end)
550 {
551 zstring::value_type ch = str[start];
552 if (info.digit_sign[0] == ch)
553 {
554 if (first_digit_sign == -1)
555 first_digit_sign = start;
556 digit_signs++;
557 }
558 else if (info.zero_digit[0] == ch)
559 {
560 last_zero_sign = start;
561 zero_signs++;
562 }
563 else if (info.grouping_separator[0] == ch)
564 part.grouping_pos.push_back(digit_signs+zero_signs);
565 start += delta;
566 }
567
568 if (first_digit_sign != -1 && last_zero_sign != -1)
569 {
570 if (!fractional && first_digit_sign > last_zero_sign)
571 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberIntegerPart)), ERROR_LOC(info.loc));
572 else if (fractional && first_digit_sign < last_zero_sign)
573 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberFractionalPart)), ERROR_LOC(info.loc));
574 }
575
576 if (part.grouping_pos.size() > 0 && part.grouping_pos[0] == 0)
577 throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberGroupingAdjacentToDecimal)), ERROR_LOC(info.loc));
578
579 if (part.grouping_pos.size() > 0)
580 {
581 part.N = part.grouping_pos[0];
582 for (unsigned int i=1; i<part.grouping_pos.size(); i++)
583 if ((part.grouping_pos[i] % part.N) != 0)
584 {
585 part.N = -1;
586 break;
587 }
588 }
589
590 part.minimum_size = zero_signs;
591 if (!fractional &&
592 zero_signs == 0 &&
593 str.find(info.decimal_separator.c_str()) == zstring::npos)
594 {
595 part.minimum_size = 1;
596 }
597
598 if (fractional)
599 part.maximum_size = digit_signs + zero_signs;
600 }
601
602
parseSubpicture(FormatNumberInfo::SubPictureInfo & sub_picture,FormatNumberInfo & info)603 static void parseSubpicture(
604 FormatNumberInfo::SubPictureInfo& sub_picture,
605 FormatNumberInfo& info)
606 {
607 int chars;
608 zstring& str = sub_picture.str;
609 if (str.empty())
610 return;
611
612 errorIfTwoOrMore(str, info.decimal_separator.c_str(), info);
613 zstring::size_type pos = str.find(info.decimal_separator.c_str());
614 if (pos != zstring::npos)
615 {
616 sub_picture.integer_part.str = str.substr(0, pos);
617 sub_picture.fractional_part.str = str.substr(pos+1, str.size()-pos);
618 }
619 else
620 sub_picture.integer_part.str = str;
621
622 parsePart(info, sub_picture.integer_part);
623 parsePart(info, sub_picture.fractional_part, true);
624
625 // prefix
626 zstring temp = sub_picture.integer_part.str;
627 chars = (int)temp.size();
628 for (int i = 0; i < chars; i++)
629 {
630 zstring::value_type ch = temp[i];
631 if (info.decimal_separator[0] == ch || info.grouping_separator[0] == ch || info.zero_digit[0] == ch
632 || info.digit_sign[0] == ch || info.pattern_separator[0] == ch || i == chars-1)
633 {
634 sub_picture.prefix = temp.substr(0, i);
635 break;
636 }
637 }
638 // suffix
639 temp = sub_picture.fractional_part.str;
640 chars = (int)temp.size();
641 for (int i=chars-1; i >= 0; i--)
642 {
643 zstring::value_type ch = temp[i];
644 if (info.decimal_separator[0] == ch || info.grouping_separator[0] == ch || info.zero_digit[0] == ch
645 || info.digit_sign[0] == ch || info.pattern_separator[0] == ch || i == 0)
646 {
647 sub_picture.suffix = temp.substr(i+1, chars-i-1);
648 break;
649 }
650 }
651 }
652
653
parsePicture(FormatNumberInfo & info)654 static void parsePicture(FormatNumberInfo& info)
655 {
656 errorIfTwoOrMore(info.pictureString, info.pattern_separator.c_str(), info);
657
658 zstring::size_type pos = info.pictureString.find(info.pattern_separator.c_str());
659 if (pos != zstring::npos)
660 {
661 info.pos_subpicture.str = info.pictureString.substr(0, pos);
662 info.neg_subpicture.str = info.pictureString.substr(pos+1, info.pictureString.size() - pos);
663 }
664 else
665 info.pos_subpicture.str = info.pictureString;
666
667 parseSubpicture(info.pos_subpicture, info);
668 if (info.neg_subpicture.str.empty())
669 {
670 info.neg_subpicture = info.pos_subpicture;
671 zstring temp(info.minus);
672 temp.append(info.pos_subpicture.prefix);
673 info.neg_subpicture.prefix = temp;
674 }
675 else
676 parseSubpicture(info.neg_subpicture, info);
677 }
678
679
isAllowedType(store::Item * type_qname)680 static bool isAllowedType(store::Item* type_qname)
681 {
682 const RootTypeManager& rtm = GENV_TYPESYSTEM;
683
684 if (type_qname->equals(rtm.XS_FLOAT_QNAME)
685 || type_qname->equals(rtm.XS_DOUBLE_QNAME)
686 || type_qname->equals(rtm.XS_DECIMAL_QNAME)
687 || type_qname->equals(rtm.XS_INTEGER_QNAME)
688 || type_qname->equals(rtm.XS_NON_POSITIVE_INTEGER_QNAME)
689 || type_qname->equals(rtm.XS_NEGATIVE_INTEGER_QNAME)
690 || type_qname->equals(rtm.XS_LONG_QNAME)
691 || type_qname->equals(rtm.XS_INT_QNAME)
692 || type_qname->equals(rtm.XS_SHORT_QNAME)
693 || type_qname->equals(rtm.XS_BYTE_QNAME)
694 || type_qname->equals(rtm.XS_NON_NEGATIVE_INTEGER_QNAME)
695 || type_qname->equals(rtm.XS_UNSIGNED_LONG_QNAME)
696 || type_qname->equals(rtm.XS_UNSIGNED_INT_QNAME)
697 || type_qname->equals(rtm.XS_UNSIGNED_SHORT_QNAME)
698 || type_qname->equals(rtm.XS_UNSIGNED_BYTE_QNAME)
699 || type_qname->equals(rtm.XS_POSITIVE_INTEGER_QNAME))
700 return true;
701 else
702 return false;
703 }
704
705 // returns n zeros "0". n can be <=0 and then the function will return ""
createZeros(int n)706 static zstring createZeros(int n)
707 {
708 zstring result;
709 // bugfix for bug #3134696
710 // if called from formatNumber with n = -1
711 if (n > 0) {
712 result.append(n, '0');
713 }
714 return result;
715 }
716
717
formatGroupings(zstring & result,const zstring & str,FormatNumberInfo::PartInfo & part,FormatNumberInfo & info)718 static void formatGroupings(
719 zstring& result,
720 const zstring& str,
721 FormatNumberInfo::PartInfo& part,
722 FormatNumberInfo& info)
723 {
724 unsigned int grouping_index = 0;
725
726 result.clear();
727
728 long len = (long)str.size();
729
730 for (long i = len-1; i >= 0; i--)
731 {
732 char ch = str[i];
733
734 if (((grouping_index < part.grouping_pos.size()
735 &&
736 len-i-1 == part.grouping_pos[grouping_index])
737 ||
738 (part.N != -1
739 &&
740 len-1-i != 0
741 &&
742 ((len-1-i) % part.N) == 0))
743 &&
744 ch != '-')
745 {
746 result.append(info.grouping_separator);
747 if (grouping_index < part.grouping_pos.size())
748 grouping_index++;
749 while (grouping_index < part.grouping_pos.size()
750 &&
751 part.grouping_pos[grouping_index] == part.grouping_pos[grouping_index-1])
752 {
753 result.append(info.grouping_separator);
754 grouping_index++;
755 }
756 }
757
758 if (ch == '0')
759 result.append(info.zero_digit);
760 else if (ch == '-')
761 ; // skip the '-' sign
762 else
763 result.push_back(ch);
764 }
765 }
766
767
formatNumber(zstring & resultString,store::Item_t & number,FormatNumberInfo & info,const TypeManager * tm,const QueryLoc & loc)768 static void formatNumber(
769 zstring& resultString,
770 store::Item_t& number,
771 FormatNumberInfo& info,
772 const TypeManager* tm,
773 const QueryLoc& loc)
774 {
775 const RootTypeManager& rtm = GENV_TYPESYSTEM;
776
777 if (number->isNaN())
778 {
779 resultString.append(info.NaN);
780 return;
781 }
782
783 store::Item_t zero;
784 store::Item_t doubleItem;
785 FormatNumberInfo::SubPictureInfo& sub_picture = info.pos_subpicture;
786
787 GENV_ITEMFACTORY->createDouble(zero, xs_double::zero());
788
789 GenericCast::castToAtomic(doubleItem, number, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
790
791 if (doubleItem->compare(zero) == -1)
792 {
793 sub_picture = info.neg_subpicture;
794 }
795
796 if (doubleItem->isPosOrNegInf())
797 {
798 resultString.append(sub_picture.prefix);
799 resultString.append(info.infinity);
800 resultString.append(sub_picture.suffix);
801 return;
802 }
803
804 xs_double adjusted = doubleItem->getDoubleValue();
805
806 if (sub_picture.str.find(info.percent) != zstring::npos)
807 adjusted *= 100;
808 else if (sub_picture.str.find(info.per_mille) != zstring::npos)
809 adjusted *= 1000;
810
811 adjusted = adjusted.roundHalfToEven(Integer(sub_picture.fractional_part.maximum_size));
812
813 zstring converted = adjusted.toString(true);
814
815 // process min sizes
816 zstring integer_part;
817 zstring fractional_part;
818 zstring::size_type pos = converted.find(".", 0, 1);
819 if (pos == zstring::npos)
820 {
821 integer_part = converted;
822 }
823 else
824 {
825 integer_part = converted.substr(0, pos);
826 fractional_part = converted.substr(pos+1, converted.size() - pos + 1);
827 }
828
829 // Add zeros
830 zstring temp = createZeros((int)(sub_picture.integer_part.minimum_size - integer_part.size()));
831 temp.append(integer_part);
832 integer_part = temp;
833 fractional_part.append(createZeros((int)(sub_picture.fractional_part.minimum_size - fractional_part.size())));
834
835 // groupings
836 zstring integer_part_result;
837 zstring fractional_part_result;
838 formatGroupings(integer_part_result, integer_part, sub_picture.integer_part, info);
839
840 zstring tmp;
841 ascii::reverse(integer_part_result, &tmp);
842 integer_part_result.swap(tmp);
843
844 tmp.clear();
845 ascii::reverse(fractional_part, &tmp);
846 fractional_part.swap(tmp);
847
848 formatGroupings(fractional_part_result,
849 fractional_part,
850 sub_picture.fractional_part,
851 info);
852
853 resultString.append(sub_picture.prefix);
854 resultString.append(integer_part_result);
855 if (fractional_part.size() != 0)
856 {
857 resultString.append(info.decimal_separator);
858 resultString.append(fractional_part_result);
859 }
860 resultString.append(sub_picture.suffix);
861 }
862
863
864 bool
nextImpl(store::Item_t & result,PlanState & planState) const865 FormatNumberIterator::nextImpl(store::Item_t& result, PlanState& planState) const
866 {
867 zstring resultString;
868 store::Item_t numberItem, pictureItem, formatName;
869 FormatNumberInfo info;
870 DecimalFormat_t df_t;
871
872 PlanIteratorState* state;
873 DEFAULT_STACK_INIT ( PlanIteratorState, state, planState );
874
875 if (!consumeNext(result, theChildren[0].getp(), planState ))
876 {
877 // Got void, assume NaN, return "NaN"
878 GENV_ITEMFACTORY->createDouble(result, xs_double::nan());
879 }
880
881 {
882 info.loc = loc;
883 if (!isAllowedType(result->getType()))
884 {
885 RAISE_ERROR(err::XPTY0004, info.loc,
886 ERROR_PARAMS(ZED(FormatNumber_2), result->getType()->getStringValue()));
887 }
888
889 consumeNext(pictureItem, theChildren[1].getp(), planState);
890
891 if (theChildren.size() < 3)
892 {
893 df_t = planState.theCompilerCB->theRootSctx->get_decimal_format(NULL);
894 }
895 else
896 {
897 do // use a do/while to avoid a horde of nested if/then/elses
898 {
899 // The formatName is a string, which must be interpreted as a QName ->
900 // must resolve the namespace, if any
901 consumeNext(formatName, theChildren[2].getp(), planState);
902 zstring tmpFormatName = formatName->getStringValue();
903 formatName = NULL;
904 if (tmpFormatName.find(':') == zstring::npos)
905 {
906 GENV_ITEMFACTORY->createQName(formatName, "", "", tmpFormatName);
907 break;
908 }
909
910 zstring ns;
911 zstring prefix = tmpFormatName.substr(0, tmpFormatName.find(':'));
912 if (theSctx->lookup_ns(ns, prefix, loc, zerr::ZXQP0000_NO_ERROR))
913 {
914 GENV_ITEMFACTORY->createQName(formatName, ns, prefix, tmpFormatName.substr(tmpFormatName.find(':')+1));
915 break;
916 }
917
918 // The prefix is not in the known namespaces, the only posibility left is for the function to be invoked from an EnclosedIterator
919 if (planState.theNodeConstuctionPath.empty())
920 {
921 throw XQUERY_EXCEPTION(err::FODF1280, ERROR_PARAMS(tmpFormatName), ERROR_LOC(loc));
922 }
923
924 store::NsBindings bindings;
925 planState.theNodeConstuctionPath.top()->getNamespaceBindings(bindings);
926 for (unsigned int i=0; i<bindings.size(); i++)
927 if (prefix == bindings[i].first)
928 {
929 GENV_ITEMFACTORY->createQName(formatName, bindings[i].second, prefix, tmpFormatName.substr(tmpFormatName.find(':')+1));
930 break;
931 }
932
933 } while(0);
934
935 if (formatName.isNull())
936 throw XQUERY_EXCEPTION(
937 err::FODF1280, ERROR_PARAMS( "<null>" ), ERROR_LOC( loc )
938 );
939
940 if ( (df_t = planState.theCompilerCB->theRootSctx->get_decimal_format(formatName)).getp() == NULL )
941 throw XQUERY_EXCEPTION(
942 err::FODF1280, ERROR_PARAMS( formatName->getStringValue() ),
943 ERROR_LOC( loc )
944 );
945
946 } // if (theChildren.size() < 3)
947
948 info.readFormat(df_t);
949
950 info.pictureString = pictureItem->getStringValue();
951 parsePicture(info);
952 formatNumber(resultString, result, info, theSctx->get_typemanager(), loc);
953
954 STACK_PUSH (GENV_ITEMFACTORY->createString(result, resultString), state);
955 }
956
957 STACK_END (state);
958 }
959
960 } // namespace zorba
961 /* vim:set et sw=2 ts=2: */
962