com.adobe.xfa.formcalc.FormCalcUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
The newest version!
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2007 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.formcalc;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/**
* This class static static utility methods
* used by the FormCalc parser.
*
* @author Mike P. Tardif
*
* @exclude from published api.
*/
final class FormCalcUtil {
/*
* Disallow instances of this class.
*/
private FormCalcUtil() {
}
static final int MAX_PRECISION = 15;
/*
* DecimalFormat objects are not thread-safe. So
* to minimize the overhead of creating a new instance each
* time we format a number, keep a partially initialized
* instance that can be cloned each time its used.
*/
static final DecimalFormat gNumberFormat
= (DecimalFormat) NumberFormat.getInstance(Locale.US);
/*
* Convert a given double to a locale-insensitive numeric string
* of given precision.
*/
static String dblToStr(double d, int p) {
if (p > MAX_PRECISION)
p = MAX_PRECISION;
//
// Convert the double to the required precision.
//
StringBuilder f = new StringBuilder();
if (p > MAX_PRECISION)
p = MAX_PRECISION;
for (int i = 0; i < 18 - p - 1; i++)
f.append('#');
f.append('0');
f.append('.');
for (int i = 0; i < p; i++)
f.append('0');
DecimalFormat oNumberFormat = (DecimalFormat) gNumberFormat.clone();
oNumberFormat.applyPattern(f.toString());
oNumberFormat.setDecimalSeparatorAlwaysShown(true);
return oNumberFormat.format(d);
}
/*
* Trim any trailing zeroes from the end of a numeric string.
*/
static int trimZeroes(StringBuilder str) {
assert(str != null);
int dot = str.indexOf(".");
int s = 0;
if (dot >= 0)
s = dot;
int e = str.length() - 1;
while (e >= s && str.charAt(e) == '0')
str.deleteCharAt(e--);
return str.length();
}
/*
* Trim any decimal point from the end of a numeric string.
*/
static int trimRadix(StringBuilder str) {
assert(str != null);
int e = str.length() - 1;
if (e >= 0 && str.charAt(e) == '.')
str.deleteCharAt(e);
return str.length();
}
/*
* Trim any sign from the start of a numeric string.
*/
static int trimSign(StringBuilder str) {
assert(str != null);
//
// Convert any +0 or -0 values to plain 0.
//
String src = str.toString();
if ("+0".equals(src) || "-0".equals(src))
str.deleteCharAt(0);
else if (src.length() >= 1 && src.charAt(0) == '+')
str.deleteCharAt(0);
return str.length();
}
/*
* Convert a locale-insensitive numeric string to a double.
*/
static double strToDbl(String str, boolean bAllowNaN /* = false */) {
assert(str != null);
double n = 0.;
try {
n = Double.parseDouble(str);
} catch (NumberFormatException e) {
if (bAllowNaN)
n = Double.NaN;
}
return n;
}
/*
* Verify if a string is a (locale-insensitive) numeric value.
*/
static boolean strIsNumeric(String str) {
if (str == null)
return false;
try {
Double.parseDouble(str);
} catch (NumberFormatException e) {
return false;
}
return true;
}
static final String hex = "0123456789ABCDEF0123456789abcdef";
private enum Surrogate { // Possible surrogate states:
Non, // non-surrogate
High, // high-surrogate
Low // low-surrogate
};
/*
* Interpolate any Unicode sequences found in string.
* The leading and trailing doublequote are ignored.
*/
static String interpolate(String src) {
assert(src != null);
int srcLen = src.length() - 1;
assert(src.charAt(0) == '"');
assert(src.charAt(srcLen) == '"');
StringBuilder buf = new StringBuilder(srcLen);
for (int i = 1; i < srcLen; i++) {
int ch = src.charAt(i);
if (ch == '"' && src.charAt(i + 1) == '"') {
buf.append((char) ch);
i++;
}
else if (ch == '\\' && src.charAt(i + 1) == 'u' && i + 5 < srcLen
&& isXDigit(src.charAt(i + 2)) && isXDigit(src.charAt(i + 3))
&& isXDigit(src.charAt(i + 4)) && isXDigit(src.charAt(i + 5))) {
ch = 0;
for (int k = 0; k < 4; k++) {
ch <<= 4;
ch += hex.indexOf(src.charAt(i + 2 + k)) & 0xf;
}
buf.append((char) ch);
i += 5;
}
else if (ch == '\\' && src.charAt(i + 1) == 'U' && i + 9 < srcLen
&& isXDigit(src.charAt(i + 2)) && isXDigit(src.charAt(i + 3))
&& isXDigit(src.charAt(i + 4)) && isXDigit(src.charAt(i + 5))
&& isXDigit(src.charAt(i + 6)) && isXDigit(src.charAt(i + 7))
&& isXDigit(src.charAt(i + 8)) && isXDigit(src.charAt(i + 9))) {
ch = 0;
for (int k = 0; k < 8; k++) {
ch <<= 4;
ch += hex.indexOf(src.charAt(i + 2 + k)) & 0xf;
}
//
// Javaport: JDK 1.4 can only handle BMP characters, so
// convert to its surrogate pair equivalent.
//
ch -= 0x10000;
buf.append((char) ((ch >> 10) | 0xd800));
buf.append((char) ((ch & 0x3ff) | 0xdc00));
i += 9;
}
else {
buf.append((char) ch);
}
}
src = buf.toString();
//
// JavaPort: ensure there are no unpaired nor any
// miss-paired surrogates.
//
Surrogate seen = Surrogate.Non;
for (int i = 0; i < src.length(); i++) {
char c = src.charAt(i);
if ('\uD800' <= c && c <= '\uDBFF') { // high surrogate
if (seen == Surrogate.High)
return null;
seen = Surrogate.High;
}
else if ('\uDC00' <= c && c <= '\uDFFF') { // low surrogate
if (seen != Surrogate.High)
return null;
seen = Surrogate.Low;
}
else { // non-surrogate
if (seen == Surrogate.High)
return null;
seen = Surrogate.Non;
}
}
return src;
}
/*
* Convert a given string to its escaped equivalent string.
* That is, escape all doublequotes with a doublequote.
*/
static String strToEscStr(String src) {
assert(src != null);
int dbq = 0;
int len = src.length();
for (int s = 0; s < len; s++) {
if (src.charAt(s) == '"')
dbq++;
}
if (dbq > 0) {
StringBuilder dst = new StringBuilder(len + dbq);
dst.setLength(len + dbq);
int p = len - 1;
int q = len + dbq - 1;
do {
if (src.charAt(p) == '"')
dst.setCharAt(q--, '"');
dst.setCharAt(q--, src.charAt(p--));
} while (p >= 0);
return dst.toString();
}
return src;
}
private static boolean isXDigit(char cChar) {
return Character.isDigit(cChar)
|| 'a' <= cChar && cChar <= 'f'
|| 'A' <= cChar && cChar <= 'F';
}
}