package org.jcodec.common.tools; import org.jcodec.common.StringUtils; import org.jcodec.platform.Platform; import java.io.File; import java.io.PrintStream; import java.lang.StringBuilder; import java.lang.System; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * @author The JCodec project * */ public class MainUtils { private static final String JCODEC_LOG_SINK_COLOR = "jcodec.colorPrint"; public static boolean isColorSupported = System.console() != null || Boolean.parseBoolean(System.getProperty(JCODEC_LOG_SINK_COLOR)); public static class Flag { private String longName; private String shortName; public Flag(String longName) { this(longName, null); } public Flag(String longName, String shortName) { this.longName = longName; this.shortName = shortName; } } public static class Cmd { public Map<String, String> flags; public String[] args; private Map<String, String>[] argFlags; public Cmd(Map<String, String> flags, String[] args, Map<String, String>[] argFlags) { this.flags = flags; this.args = args; this.argFlags = argFlags; } private Long getLongFlagInternal(Map<String, String> flags, String flagName, Long defaultValue) { return flags.containsKey(flagName) ? new Long(flags.get(flagName)) : defaultValue; } private Integer getIntegerFlagInternal(Map<String, String> flags, String flagName, Integer defaultValue) { return flags.containsKey(flagName) ? new Integer(flags.get(flagName)) : defaultValue; } private Boolean getBooleanFlagInternal(Map<String, String> flags, String flagName, Boolean defaultValue) { return flags.containsKey(flagName) ? !"false".equalsIgnoreCase(flags.get(flagName)) : defaultValue; } private Double getDoubleFlagInternal(Map<String, String> flags, String flagName, Double defaultValue) { return flags.containsKey(flagName) ? new Double(flags.get(flagName)) : defaultValue; } private String getStringFlagInternal(Map<String, String> flags, String flagName, String defaultValue) { return flags.containsKey(flagName) ? flags.get(flagName) : defaultValue; } private int[] getMultiIntegerFlagInternal(Map<String, String> flags, String flagName, int[] defaultValue) { if (!flags.containsKey(flagName)) return defaultValue; String[] split = StringUtils.splitS(flags.get(flagName), ","); int[] result = new int[split.length]; for (int i = 0; i < split.length; i++) result[i] = Integer.parseInt(split[i]); return result; } private <T extends Enum<T>> T getEnumFlagInternal(Map<String, String> flags, String flagName, T defaultValue, Class<T> class1) { if (!flags.containsKey(flagName)) return defaultValue; String strVal = flags.get(flagName).toLowerCase(); EnumSet<T> allOf = EnumSet.allOf(class1); for (T val : allOf) { if (val.name().toLowerCase().equals(strVal)) return val; } return null; } public Long getLongFlagD(String flagName, Long defaultValue) { return this.getLongFlagInternal(flags, flagName, defaultValue); } public Long getLongFlag(String flagName) { return this.getLongFlagInternal(flags, flagName, null); } public Long getLongFlagID(int arg, String flagName, Long defaultValue) { return this.getLongFlagInternal(argFlags[arg], flagName, defaultValue); } public Long getLongFlagI(int arg, String flagName) { return this.getLongFlagInternal(argFlags[arg], flagName, null); } public Integer getIntegerFlagD(String flagName, Integer defaultValue) { return getIntegerFlagInternal(flags, flagName, defaultValue); } public Integer getIntegerFlag(String flagName) { return getIntegerFlagInternal(flags, flagName, null); } public Integer getIntegerFlagID(int arg, String flagName, Integer defaultValue) { return getIntegerFlagInternal(argFlags[arg], flagName, defaultValue); } public Integer getIntegerFlagI(int arg, String flagName) { return getIntegerFlagInternal(argFlags[arg], flagName, null); } public Boolean getBooleanFlagD(String flagName, Boolean defaultValue) { return getBooleanFlagInternal(flags, flagName, defaultValue); } public Boolean getBooleanFlag(String flagName) { return getBooleanFlagInternal(flags, flagName, false); } public Boolean getBooleanFlagID(int arg, String flagName, Boolean defaultValue) { return getBooleanFlagInternal(argFlags[arg], flagName, defaultValue); } public Boolean getBooleanFlagI(int arg, String flagName) { return getBooleanFlagInternal(argFlags[arg], flagName, null); } public Double getDoubleFlagD(String flagName, Double defaultValue) { return getDoubleFlagInternal(flags, flagName, defaultValue); } public Double getDoubleFlag(String flagName) { return getDoubleFlagInternal(flags, flagName, null); } public Double getDoubleFlagID(int arg, String flagName, Double defaultValue) { return getDoubleFlagInternal(argFlags[arg], flagName, defaultValue); } public Double getDoubleFlagI(int arg, String flagName) { return getDoubleFlagInternal(argFlags[arg], flagName, null); } public String getStringFlagD(String flagName, String defaultValue) { return getStringFlagInternal(flags, flagName, defaultValue); } public String getStringFlag(String flagName) { return getStringFlagInternal(flags, flagName, null); } public String getStringFlagID(int arg, String flagName, String defaultValue) { return getStringFlagInternal(argFlags[arg], flagName, defaultValue); } public String getStringFlagI(int arg, String flagName) { return getStringFlagInternal(argFlags[arg], flagName, null); } public int[] getMultiIntegerFlagD(String flagName, int[] defaultValue) { return getMultiIntegerFlagInternal(flags, flagName, defaultValue); } public int[] getMultiIntegerFlag(String flagName) { return getMultiIntegerFlagInternal(flags, flagName, new int[0]); } public int[] getMultiIntegerFlagID(int arg, String flagName, int[] defaultValue) { return getMultiIntegerFlagInternal(argFlags[arg], flagName, defaultValue); } public int[] getMultiIntegerFlagI(int arg, String flagName) { return getMultiIntegerFlagInternal(argFlags[arg], flagName, new int[0]); } public <T extends Enum<T>> T getEnumFlagD(String flagName, T defaultValue, Class<T> class1) { return getEnumFlagInternal(flags, flagName, defaultValue, class1); } public <T extends Enum<T>> T getEnumFlag(String flagName, Class<T> class1) { return getEnumFlagInternal(flags, flagName, null, class1); } public <T extends Enum<T>> T getEnumFlagID(int arg, String flagName, T defaultValue, Class<T> class1) { return getEnumFlagInternal(argFlags[arg], flagName, defaultValue, class1); } public <T extends Enum<T>> T getEnumFlagI(int arg, String flagName, Class<T> class1) { return getEnumFlagInternal(argFlags[arg], flagName, null, class1); } public String getArg(int i) { return i < args.length ? args[i] : null; } public int argsLength() { return args.length; } public void popArg() { args = Platform.copyOfRangeO(args, 1, args.length); } } private static Pattern flagPattern = Pattern.compile("^--([^=]+)=(.*)$"); public static Cmd parseArguments(String[] args) { Map<String, String> flags = new HashMap<String, String>(); Map<String, String> allFlags = new HashMap<String, String>(); List<String> outArgs = new ArrayList<String>(); List<Map<String, String>> argFlags = new ArrayList<Map<String, String>>(); int arg = 0; for (; arg < args.length; arg++) { if (args[arg].startsWith("--")) { Matcher matcher = flagPattern.matcher(args[arg]); if (matcher.matches()) { flags.put(matcher.group(1), matcher.group(2)); } else { flags.put(args[arg].substring(2), "true"); } } else if (args[arg].startsWith("-")) { flags.put(args[arg].substring(1), args[++arg]); } else { allFlags.putAll(flags); outArgs.add(args[arg]); argFlags.add(flags); } } return new Cmd(allFlags, outArgs.toArray(new String[0]), argFlags.toArray((Map<String, String>[]) Array .newInstance(flags.getClass(), 0))); } public static void printHelpVarArgs(Map<String, String> flags, String ... arguments) { printHelpOut(System.out, "", flags, Arrays.asList(arguments)); } public static void printHelpArgs(Map<String, String> flags, String [] arguments) { printHelpOut(System.out, "", flags, Arrays.asList(arguments)); } public static void printHelp(Map<String, String> flags, List<String> params) { printHelpOut(System.out, "", flags, params); } public static void printHelpNoFlags(String... arguments) { printHelpOut(System.out, "", new HashMap<String, String>(), Arrays.asList(arguments)); } public static void printHelpCmd(String command, Map<String, String> flags, List<String> params) { printHelpOut(System.out, command, flags, params); } public static void printHelpOut(PrintStream out, String command, Map<String, String> flags, List<String> params) { out.print(bold("Syntax: " + command)); StringBuilder sample = new StringBuilder(); StringBuilder detail = new StringBuilder(); for (Entry<String, String> entry : flags.entrySet()) { sample.append(" [" + bold(color("--" + entry.getKey() + "=<value>", ANSIColor.MAGENTA)) + "]"); detail.append("\t" + bold(color("--" + entry.getKey(), ANSIColor.MAGENTA)) + "\t\t" + entry.getValue() + "\n"); } for (String param : params) { if (param.charAt(0) != '?') sample.append(bold(" <" + param + ">")); else sample.append(bold(" [" + param.substring(1) + "]")); } out.println(sample); out.println(bold("Where:")); out.println(detail); } public enum ANSIColor { BLACK, RED, GREEN, BROWN, BLUE, MAGENTA, CYAN, GREY } public static String bold(String str) { return isColorSupported ? "\033[1m" + str + "\033[0m" : str; } public static String colorString(String str, String placeholder) { return isColorSupported ? "\033[" + placeholder + "m" + str + "\033[0m" : str; } public static String color(String str, ANSIColor fg) { return isColorSupported ? "\033[" + (30 + (fg.ordinal() & 0x7)) + "m" + str + "\033[0m" : str; } public static String colorBright(String str, ANSIColor fg, boolean bright) { return isColorSupported ? "\033[" + (30 + (fg.ordinal() & 0x7)) + ";" + (bright ? 1 : 2) + "m" + str + "\033[0m" : str; } public static String color3(String str, ANSIColor fg, ANSIColor bg) { return isColorSupported ? "\033[" + (30 + (fg.ordinal() & 0x7)) + ";" + (40 + (bg.ordinal() & 0x7)) + ";1m" + str + "\033[0m" : str; } public static String color4(String str, ANSIColor fg, ANSIColor bg, boolean bright) { return isColorSupported ? "\033[" + (30 + (fg.ordinal() & 0x7)) + ";" + (40 + (bg.ordinal() & 0x7)) + ";" + (bright ? 1 : 2) + "m" + str + "\033[0m" : str; } public static File tildeExpand(String path) { if (path.startsWith("~")) { path = path.replaceFirst("~", System.getProperty("user.home")); } return new File(path); } }