package com.github.sommeri.less4j.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.ASTCssNodeType;
import com.github.sommeri.less4j.core.parser.LessParser;
import com.github.sommeri.less4j.core.problems.ProblemsHandler;
public class PrintUtils {
private static final DecimalFormat FORMATTER = createFormatter();
private static final DecimalFormat FORMATTER_TWO_DECIMAL = createFormatter2();
private static DecimalFormat createFormatter() {
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
return new DecimalFormat("#.##################", symbols);
}
private static DecimalFormat createFormatter2() {
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
return new DecimalFormat("#.####", symbols);
}
public static String formatNumber(Long value) {
return formatNumber(value.doubleValue());
}
public static String formatNumber(Double value) {
if (value.isNaN())
return "NaN";
return FORMATTER.format(value);
}
public static String formatNumberTwoDecimal(Long value) {
return formatNumberTwoDecimal(value.doubleValue());
}
public static String formatNumberTwoDecimal(Double value) {
if (value.isNaN())
return "NaN";
return FORMATTER_TWO_DECIMAL.format(value);
}
public static String formatNumber(Number value) {
return FORMATTER.format(value);
}
public static String toName(int tokenType) {
if (tokenType == -1)
return "EOF";
if (tokenType >= LessParser.tokenNames.length)
return "Unknown: " + tokenType;
return LessParser.tokenNames[tokenType];
}
public static String toUtf8ExceptURL(String value) {
String encode = toUtf8(value);
encode = encode.replaceAll("\\+", "%20").replaceAll("%2C", ",").replaceAll("%2F", "/").replaceAll("%3F", "?");
encode = encode.replaceAll("%40", "@").replaceAll("%26", "&").replaceAll("%2B", "+");
encode = encode.replaceAll("%27", "'").replaceAll("%7E", "~").replaceAll("%21", "!");
encode = encode.replace("%24", "$"); //replaceAll crash on this
return encode;
}
/**
* Port of javascript encodeURIComponent.
*
* Converts into utf-8 except following characters * - _ . ! ~ * ' ( )
*/
public static String toUtf8AsUri(String value) { //
String encode = toUtf8(value);
encode = encode.replaceAll("\\+", "%20").replaceAll("%2D", "_").replaceAll("%2E", ".");
encode = encode.replaceAll("%21", "!").replaceAll("%7E", "~").replaceAll("%2A", "*");
encode = encode.replaceAll("%27", "'").replaceAll("%28", "(").replaceAll("%29", ")");
return encode;
}
public static String toUtf8ExceptGrrr(String value) {
String encode = toUtf8(value);
encode = encode.replaceAll("\\+", "%20");
encode = encode.replaceAll("%28", "(").replaceAll("%29", ")");
encode = encode.replaceAll("%27", "'").replaceAll("%7E", "~").replaceAll("%21", "!");
return encode;
}
public static String urlEncode(String toEncode, String encodingCharset, ProblemsHandler problemsHandler, ASTCssNode nodeForErrorReport) {
if (toEncode==null || encodingCharset==null)
return null;
try {
return URLEncoder.encode(toEncode, encodingCharset);
} catch (UnsupportedEncodingException uex) {
problemsHandler.errUnknownEncodingCharsetSourceMap(nodeForErrorReport, encodingCharset);
return null;
}
}
public static String base64Encode(String toEncode, String encodingCharset, ProblemsHandler problemsHandler, ASTCssNode nodeForErrorReport) {
try {
return Base64.encodeBytes(toEncode.getBytes(encodingCharset));
} catch (UnsupportedEncodingException uex) {
problemsHandler.errUnknownEncodingCharsetSourceMap(nodeForErrorReport, encodingCharset);
return null;
}
}
public static String toUtf8(String value) {
try {
return URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
}
public static String toTypeName(ASTCssNode node) {
return toTypeName(node.getType());
}
public static String toTypeNames(ASTCssNodeType... types) {
String result = "";
for (ASTCssNodeType type : types) {
if (!result.isEmpty())
result += " or ";
result += toTypeName(type);
}
return result;
}
public static String toTypeName(ASTCssNodeType type) {
switch (type) {
case DECLARATION:
return "declaration";
case KEYFRAMES:
return "@keyframes";
case DOCUMENT:
return "@document";
case STYLE_SHEET:
return "top level style sheet";
case INDIRECT_VARIABLE:
return "indirect variable";
case VARIABLE:
return "expression";
case NUMBER:
return "number";
case NAMED_EXPRESSION:
return "identifier";
case IDENTIFIER_EXPRESSION:
return "identifier";
case FUNCTION:
return "function";
case FAULTY_EXPRESSION:
return "faulty expression";
case ESCAPED_VALUE:
return "escaped value";
case EMPTY_EXPRESSION:
return "empty expression";
case COLOR_EXPRESSION:
return "color";
case STRING_EXPRESSION:
return "string";
case RULE_SET:
return "rule set";
case PAGE:
return "@page";
case PAGE_MARGIN_BOX:
return "page margin box";
default:
//FIXME (hign priority) replace by something safer - ASAP
return type.name();
}
}
public static String toLocation(ASTCssNode node) {
return node.getSourceLine() + ":" + node.getSourceColumn();
}
public static String base64Encode(byte[] data) {
return Base64.encodeBytes(data);
}
public static String toString(String[] strings) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (String string : strings) {
if (!first)
result.append(", ");
result.append(string);
first = false;
}
return result.toString();
}
}