/* * Fernflower - The Analytical Java Decompiler * http://www.reversed-java.com * * (C) 2008 - 2010, Stiver * * This software is NEITHER public domain NOR free software * as per GNU License. See license.txt for more details. * * This software is distributed WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. */ package org.jetbrains.java.decompiler.util; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.Map.Entry; import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet; public class SFormsFastMapDirect { private int size; private FastSparseSet[][] elements = new FastSparseSet[3][]; private int[][] next = new int[3][]; public SFormsFastMapDirect() { this(true); } private SFormsFastMapDirect(boolean initialize) { if(initialize) { for(int i=2; i>=0; i--) { elements[i] = new FastSparseSet[0]; next[i] = new int[0]; } } } public SFormsFastMapDirect(SFormsFastMapDirect map) { for(int i=2;i>=0;i--) { FastSparseSet[] arr = map.elements[i]; int[] arrnext = map.next[i]; int length = arr.length; FastSparseSet[] arrnew = new FastSparseSet[length]; int[] arrnextnew = new int[length]; System.arraycopy(arr, 0, arrnew, 0, length); System.arraycopy(arrnext, 0, arrnextnew, 0, length); elements[i] = arrnew; next[i] = arrnextnew; size = map.size; } } public SFormsFastMapDirect getCopy() { SFormsFastMapDirect map = new SFormsFastMapDirect(false); map.size = size; FastSparseSet[][] mapelements = map.elements; int[][] mapnext = map.next; for(int i=2;i>=0;i--) { FastSparseSet[] arr = elements[i]; int length = arr.length; if(length > 0) { int[] arrnext = next[i]; FastSparseSet[] arrnew = new FastSparseSet[length]; int[] arrnextnew = new int[length]; System.arraycopy(arrnext, 0, arrnextnew, 0, length); mapelements[i] = arrnew; mapnext[i] = arrnextnew; int pointer = 0; do { FastSparseSet set = arr[pointer]; if(set != null) { arrnew[pointer] = set.getCopy(); } pointer = arrnext[pointer]; } while(pointer != 0); } else { mapelements[i] = new FastSparseSet[0]; mapnext[i] = new int[0]; } } return map; } public int size() { return size; } public boolean isEmpty() { return size == 0; } public void put(int key, FastSparseSet value) { putInternal(key, value, false); } public void remove(int key) { putInternal(key, null, true); } public void removeAllFields() { FastSparseSet[] arr = elements[2]; int[] arrnext = next[2]; for(int i=arr.length-1;i>=0;i--) { FastSparseSet val = arr[i]; if(val != null) { arr[i] = null; size--; } arrnext[i] = 0; } } public void putInternal(final int key, final FastSparseSet value, boolean remove) { int index = 0; int ikey = key; if(ikey < 0) { index = 2; ikey = -ikey; } else if(ikey >= VarExprent.STACK_BASE) { index = 1; ikey -= VarExprent.STACK_BASE; } FastSparseSet[] arr = elements[index]; if(ikey >= arr.length) { if(remove) { return; } else { arr = ensureCapacity(index, ikey+1, false); } } FastSparseSet oldval = arr[ikey]; arr[ikey] = value; int[] arrnext = next[index]; if(oldval == null && value != null) { size++; changeNext(arrnext, ikey, arrnext[ikey], ikey); } else if(oldval != null && value == null) { size--; changeNext(arrnext, ikey, ikey, arrnext[ikey]); } } private void changeNext(int[] arrnext, int key, int oldnext, int newnext) { for(int i=key-1;i>=0;i--) { if(arrnext[i] == oldnext) { arrnext[i] = newnext; } else { break; } } } public boolean containsKey(int key) { return get(key) != null; } public FastSparseSet get(int key) { int index = 0; if(key < 0) { index = 2; key = -key; } else if(key >= VarExprent.STACK_BASE) { index = 1; key -= VarExprent.STACK_BASE; } FastSparseSet[] arr = elements[index]; if(key < arr.length) { return arr[key]; } return null; } public void complement(SFormsFastMapDirect map) { for(int i=2;i>=0;i--) { FastSparseSet[] lstOwn = elements[i]; if(lstOwn.length == 0) { continue; } FastSparseSet[] lstExtern = map.elements[i]; int[] arrnext = next[i]; int pointer = 0; do { FastSparseSet first = lstOwn[pointer]; if(first != null) { if(pointer >= lstExtern.length) { break; } FastSparseSet second = lstExtern[pointer]; if(second != null) { first.complement(second); if(first.isEmpty()) { lstOwn[pointer] = null; size--; changeNext(arrnext, pointer, pointer, arrnext[pointer]); } } } pointer = arrnext[pointer]; } while(pointer != 0); } } public void intersection(SFormsFastMapDirect map) { for(int i=2;i>=0;i--) { FastSparseSet[] lstOwn = elements[i]; if(lstOwn.length == 0) { continue; } FastSparseSet[] lstExtern = map.elements[i]; int[] arrnext = next[i]; int pointer = 0; do { FastSparseSet first = lstOwn[pointer]; if(first != null) { FastSparseSet second = null; if(pointer < lstExtern.length) { second = lstExtern[pointer]; } if(second != null) { first.intersection(second); } if(second == null || first.isEmpty()) { lstOwn[pointer] = null; size--; changeNext(arrnext, pointer, pointer, arrnext[pointer]); } } pointer = arrnext[pointer]; } while(pointer != 0); } } public void union(SFormsFastMapDirect map) { for(int i=2;i>=0;i--) { FastSparseSet[] lstExtern = map.elements[i]; if(lstExtern.length == 0) { continue; } FastSparseSet[] lstOwn = elements[i]; int[] arrnext = next[i]; int[] arrnextExtern = map.next[i]; int pointer = 0; do { if(pointer >= lstOwn.length) { lstOwn = ensureCapacity(i, lstExtern.length, true); arrnext = next[i]; } FastSparseSet second = lstExtern[pointer]; if(second != null) { FastSparseSet first = lstOwn[pointer]; if(first == null) { lstOwn[pointer] = second.getCopy(); size++; changeNext(arrnext, pointer, arrnext[pointer], pointer); } else { first.union(second); } } pointer = arrnextExtern[pointer]; } while(pointer != 0); } } public String toString() { StringBuilder buffer = new StringBuilder("{"); List>> lst = entryList(); if(lst != null) { boolean first = true; for(Entry> entry : lst) { if(!first) { buffer.append(", "); } else { first = false; } Set set = entry.getValue().toPlainSet(); buffer.append(entry.getKey()+"={"+set.toString()+"}"); } } buffer.append("}"); return buffer.toString(); } public List>> entryList() { List>> list = new ArrayList>>(); for(int i=2;i>=0;i--) { int ikey = 0; for(final FastSparseSet ent : elements[i]) { if(ent != null) { final int key = i==0?ikey:(i==1?ikey+VarExprent.STACK_BASE:-ikey); list.add(new Entry>() { private Integer var = key; private FastSparseSet val = ent; public Integer getKey() { return var; } public FastSparseSet getValue() { return val; } public FastSparseSet setValue(FastSparseSet newvalue) { return null; } }); } ikey++; } } return list; } private FastSparseSet[] ensureCapacity(int index, int size, boolean exact) { FastSparseSet[] arr = elements[index]; int[] arrnext = next[index]; int minsize = size; if(!exact) { minsize = 2*arr.length/3 +1; if(size > minsize) { minsize = size; } } FastSparseSet[] arrnew = new FastSparseSet[minsize]; System.arraycopy(arr, 0, arrnew, 0, arr.length); int[] arrnextnew = new int[minsize]; System.arraycopy(arrnext, 0, arrnextnew, 0, arrnext.length); elements[index] = arrnew; next[index] = arrnextnew; return arrnew; } }