package com.github.sommeri.less4j.utils; import java.nio.ByteBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.github.sommeri.less4j.core.ast.SelectorPart; public class ArraysUtils { public interface Filter<T> { public boolean accept(T t); } public static <T> T[] asArray(T... args) { return args; } public static <T> Set<T> asSet(T... args) { return new HashSet<T>(Arrays.asList(args)); } public static <T> List<T> asList(T... args) { return new ArrayList<T>(Arrays.asList(args)); } public static <T> int count(Collection<T> collection, Filter<T> filter) { int result = 0; for (T t : collection) { if (filter.accept(t)) result++; } return result; } public static <T> List<T> sameLengthSuffix(List<T> ofList, List<T> asThis) { if (asThis.size()>ofList.size()) return null; int to = ofList.size(); int from = to - asThis.size(); return ofList.subList(from, to); } public static <T> List<T> sameLengthPrefix(List<T> ofList, List<T> asThis) { if (asThis.size()>ofList.size()) return null; return ofList.subList(0, asThis.size()); } public static <T> List<T> sublistWithoutLast(List<T> values) { if (values.isEmpty()) return null; return values.subList(0, values.size()-1); } public static <T> List<T> sublistWithoutFirst(List<T> values) { if (values.isEmpty()) return null; return values.subList(1, values.size()); } public static <T> List<T> safeSublist(List<T> values, int from, int to) { if (values.isEmpty()) return null; if (from>to) return new ArrayList<T>(); if (from>values.size()) from=values.size(); if (to>values.size()) to=values.size(); return values.subList(from, to); } public static <T> T last(List<T> values) { if (values.isEmpty()) return null; return values.get(values.size() - 1); } public static <T> T chopLast(List<T> values) { if (values.isEmpty()) return null; return values.remove(values.size() - 1); } public static <T> T first(List<T> values) { if (values.isEmpty()) return null; return values.get(0); } public static <T> T chopFirst(List<T> values) { if (values.isEmpty()) return null; return values.remove(0); } public static <T> List<T> chopUpTo(List<T> list, T exclusiveTo) { int indx = list.indexOf(exclusiveTo); if (indx == -1) return new ArrayList<T>(); List<T> subList = list.subList(0, indx); List<T> result = new ArrayList<T>(subList); subList.clear(); return result; } public static <T> List<T> chopPrefix(List<T> list, int exclusiveTo) { if (exclusiveTo > list.size()) exclusiveTo = list.size(); List<T> subList = list.subList(0, exclusiveTo); List<T> result = new ArrayList<T>(subList); subList.clear(); return result; } public static <T> List<T> asNonNullList(T... a) { List<T> result = new ArrayList<T>(); for (T t : a) { if (t != null) result.add(t); } return result; } public static <T> List<T> addIfNonNull(List<T> destination, T... a) { for (T t : a) { if (t != null) destination.add(t); } return destination; } @SuppressWarnings("unchecked") public static <T extends PubliclyCloneable> List<T> deeplyClonedList(List<T> list) { List<T> result = new ArrayList<T>(); for (T t : list) { result.add((T)t.clone()); } return result; } @SuppressWarnings("unchecked") public static <T extends PubliclyCloneable> LinkedList<T> deeplyClonedLinkedList(LinkedList<T> list) { LinkedList<T> result = new LinkedList<T>(); for (T t : list) { result.add((T)t.clone()); } return result; } @SuppressWarnings("unchecked") public static <M, T extends PubliclyCloneable> Map<M, T> deeplyClonedMap(Map<M, T> map) { Map<M, T> result = new HashMap<M, T>(); for (Entry<M, T> t : map.entrySet()) { result.put(t.getKey(), (T)(t.getValue().clone())); } return result; } public static <M, T extends PubliclyCloneable> Map<M, List<T>> deeplyClonedListInMap(Map<M, List<T>> map) { Map<M, List<T>> result = new HashMap<M, List<T>>(); for (Entry<M, List<T>> t : map.entrySet()) { result.put(t.getKey(), deeplyClonedList(t.getValue())); } return result; } public static <T> List<T> remaining(Iterator<T> iterator) { List<T> result = new ArrayList<T>(); while (iterator.hasNext()) result.add(iterator.next()); return result; } public static <T> List<T> asModifiableList(T... head) { List<T> result = new ArrayList<T>(); for (T t : head) { result.add(t); } return result; } public static <T> List<T> joinAll(List<T>... lists) { List<T> result = new ArrayList<T>(); for (List<T> t : lists) { result.addAll(t); } return result; } public static <T> void replace(SelectorPart lookFor, List<T> inside, List<T> replaceBy) { int indx = inside.indexOf(lookFor); inside.remove(lookFor); inside.addAll(indx, replaceBy); } public static boolean isUtf8(byte[] input) { return isEncodedAs(input, "UTF-8"); } public static boolean isUsAscii(byte[] input) { return isEncodedAs(input, "US-ASCII"); } public static boolean isEncodedAs(byte[] input, String encoding) { CharsetDecoder decoder = Charset.forName(encoding).newDecoder().onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT); try { decoder.decode(ByteBuffer.wrap(input)); } catch (CharacterCodingException e) { return false; } return true; } public static <Q> void replace(List<Q> inList, Q oldElement, LinkedList<Q> newElements) { int level = inList.indexOf(oldElement); inList.remove(level); inList.addAll(level, newElements); } }