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