Example #1
0
  /**
   * Analyze a picture string into two sub-pictures.
   *
   * @param picture the picture as written (possibly two subpictures separated by a semicolon)
   * @param dfs the decimal format symbols
   * @return an array of two sub-pictures, the positive and the negative sub-pictures respectively.
   *     If there is only one sub-picture, the second one is null.
   */
  private SubPicture[] getSubPictures(String picture, DecimalSymbols dfs) throws XPathException {
    int[] picture4 = StringValue.expand(picture);
    SubPicture[] pics = new SubPicture[2];
    if (picture4.length == 0) {
      XPathException err = new XPathException("format-number() picture is zero-length");
      err.setErrorCode("XTDE1310");
      throw err;
    }
    int sep = -1;
    for (int c = 0; c < picture4.length; c++) {
      if (picture4[c] == dfs.patternSeparator) {
        if (c == 0) {
          grumble("first subpicture is zero-length");
        } else if (sep >= 0) {
          grumble("more than one pattern separator");
        } else if (sep == picture4.length - 1) {
          grumble("second subpicture is zero-length");
        }
        sep = c;
      }
    }

    if (sep < 0) {
      pics[0] = new SubPicture(picture4, dfs);
      pics[1] = null;
    } else {
      int[] pic0 = new int[sep];
      System.arraycopy(picture4, 0, pic0, 0, sep);
      int[] pic1 = new int[picture4.length - sep - 1];
      System.arraycopy(picture4, sep + 1, pic1, 0, picture4.length - sep - 1);
      pics[0] = new SubPicture(pic0, dfs);
      pics[1] = new SubPicture(pic1, dfs);
    }
    return pics;
  }
Example #2
0
    /**
     * Format a number using this sub-picture
     *
     * @param value the absolute value of the number to be formatted
     * @param dfs the decimal format symbols to be used
     * @param minusSign the representation of a minus sign to be used
     * @return the formatted number
     */
    public CharSequence format(NumericValue value, DecimalSymbols dfs, String minusSign) {

      // System.err.println("Formatting " + value);

      if (value.isNaN()) {
        return dfs.NaN; // changed by W3C Bugzilla 2712
      }

      if ((value instanceof DoubleValue || value instanceof FloatValue)
          && Double.isInfinite(value.getDoubleValue())) {
        return minusSign + prefix + dfs.infinity + suffix;
      }

      int multiplier = 1;
      if (isPercent) {
        multiplier = 100;
      } else if (isPerMille) {
        multiplier = 1000;
      }

      if (multiplier != 1) {
        try {
          // value = value.arithmetic(Token.MULT, new Int64Value(multiplier), null);
          value =
              (NumericValue)
                  ArithmeticExpression.compute(
                      value, Calculator.TIMES, new Int64Value(multiplier), null);
        } catch (XPathException e) {
          value = new DoubleValue(value.getDoubleValue() * multiplier);
        }
      }

      FastStringBuffer sb = new FastStringBuffer(20);
      if (value instanceof DoubleValue || value instanceof FloatValue) {
        BigDecimal dec = adjustToDecimal(value.getDoubleValue(), 2);
        formatDecimal(dec, sb);

        // formatDouble(value.getDoubleValue(), sb);

      } else if (value instanceof Int64Value || value instanceof BigIntegerValue) {
        formatInteger(value, sb);

      } else if (value instanceof DecimalValue) {
        //noinspection RedundantCast
        formatDecimal(((DecimalValue) value).getDecimalValue(), sb);
      }

      // System.err.println("Justified number: " + sb.toString());

      // Map the digits and decimal point to use the selected characters

      int[] ib = StringValue.expand(sb);
      int ibused = ib.length;
      int point = sb.indexOf('.');
      if (point == -1) {
        point = sb.length();
      } else {
        ib[point] = dfs.decimalSeparator;

        // If there is no fractional part, delete the decimal point
        if (maxFractionPartSize == 0) {
          ibused--;
        }
      }

      // Map the digits

      if (dfs.zeroDigit != '0') {
        int newZero = dfs.zeroDigit;
        for (int i = 0; i < ibused; i++) {
          int c = ib[i];
          if (c >= '0' && c <= '9') {
            ib[i] = (c - '0' + newZero);
          }
        }
      }

      // Add the whole-part grouping separators

      if (wholePartGroupingPositions != null) {
        if (wholePartGroupingPositions.length == 1) {
          // grouping separators are at regular positions
          int g = wholePartGroupingPositions[0];
          int p = point - g;
          while (p > 0) {
            ib = insert(ib, ibused++, dfs.groupingSeparator, p);
            // sb.insert(p, unicodeChar(dfs.groupingSeparator));
            p -= g;
          }
        } else {
          // grouping separators are at irregular positions
          for (int i = 0; i < wholePartGroupingPositions.length; i++) {
            int p = point - wholePartGroupingPositions[i];
            if (p > 0) {
              ib = insert(ib, ibused++, dfs.groupingSeparator, p);
              // sb.insert(p, unicodeChar(dfs.groupingSeparator));
            }
          }
        }
      }

      // Add the fractional-part grouping separators

      if (fractionalPartGroupingPositions != null) {
        // grouping separators are at irregular positions.
        for (int i = 0; i < fractionalPartGroupingPositions.length; i++) {
          int p = point + 1 + fractionalPartGroupingPositions[i] + i;
          if (p < ibused - 1) {
            ib = insert(ib, ibused++, dfs.groupingSeparator, p);
            // sb.insert(p, dfs.groupingSeparator);
          } else {
            break;
          }
        }
      }

      // System.err.println("Grouped number: " + sb.toString());

      // sb.insert(0, prefix);
      // sb.insert(0, minusSign);
      // sb.append(suffix);
      FastStringBuffer res =
          new FastStringBuffer(prefix.length() + minusSign.length() + suffix.length() + ibused);
      res.append(minusSign);
      res.append(prefix);
      res.append(StringValue.contract(ib, ibused));
      res.append(suffix);
      return res;
    }