All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.formcalc.FormCalcUtil Maven / Gradle / Ivy

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';
	}

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy