commit 7d26cb34a181b322716303c815c28802f4e05a3d Author: Merith-TK Date: Tue Aug 9 23:01:55 2022 -0700 decompile with cfr diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afc0f2b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +cfr.jar \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..f2874b1 --- /dev/null +++ b/Readme.md @@ -0,0 +1,5 @@ +decompiled SkaiaCraft launcher with personal tweaks and bugfixes + +## Disclaimer +* Decompiled with [CFR](http://www.benf.org/other/cfr/) + * Made easier with [My CFR Helper](https://github.com/Merith-TK/cfr) \ No newline at end of file diff --git a/skaiacraft_v3.jar b/skaiacraft_v3.jar new file mode 100644 index 0000000..74d2af1 Binary files /dev/null and b/skaiacraft_v3.jar differ diff --git a/src/Log4j-config.xsd b/src/Log4j-config.xsd new file mode 100644 index 0000000..a19e125 --- /dev/null +++ b/src/Log4j-config.xsd @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Log4j-events.dtd b/src/Log4j-events.dtd new file mode 100644 index 0000000..d6b34c8 --- /dev/null +++ b/src/Log4j-events.dtd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Log4j-events.xsd b/src/Log4j-events.xsd new file mode 100644 index 0000000..6e18154 --- /dev/null +++ b/src/Log4j-events.xsd @@ -0,0 +1,78 @@ + + + + + + Log4J 2.0 XML Schema for XML log event files. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Log4j-levels.xsd b/src/Log4j-levels.xsd new file mode 100644 index 0000000..3ca10bb --- /dev/null +++ b/src/Log4j-levels.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..8ebbf15 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Implementation-Version: v1.0 +Archiver-Version: Plexus Archiver +Built-By: Andrew +Created-By: Apache Maven 3.0.5 +Build-Jdk: 1.8.0_171 +Main-Class: net.mc.main.Main + diff --git a/src/Minecraft_Logo.png b/src/Minecraft_Logo.png new file mode 100644 index 0000000..5049c74 Binary files /dev/null and b/src/Minecraft_Logo.png differ diff --git a/src/cakehoohoohoo.png b/src/cakehoohoohoo.png new file mode 100644 index 0000000..2947892 Binary files /dev/null and b/src/cakehoohoohoo.png differ diff --git a/src/com/evilco/mc/nbt/error/TagNotFoundException.java b/src/com/evilco/mc/nbt/error/TagNotFoundException.java new file mode 100644 index 0000000..6b3f46c --- /dev/null +++ b/src/com/evilco/mc/nbt/error/TagNotFoundException.java @@ -0,0 +1,27 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.error; + +import java.io.IOException; + +public class TagNotFoundException +extends IOException { + private static final long serialVersionUID = -4631008535746749103L; + + public TagNotFoundException() { + super("The tag does not exist"); + } + + public TagNotFoundException(String message) { + super(message); + } + + public TagNotFoundException(Throwable cause) { + super(cause); + } + + public TagNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/com/evilco/mc/nbt/error/UnexpectedTagTypeException.java b/src/com/evilco/mc/nbt/error/UnexpectedTagTypeException.java new file mode 100644 index 0000000..0360248 --- /dev/null +++ b/src/com/evilco/mc/nbt/error/UnexpectedTagTypeException.java @@ -0,0 +1,27 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.error; + +import java.io.IOException; + +public class UnexpectedTagTypeException +extends IOException { + private static final long serialVersionUID = -6604963428978583800L; + + public UnexpectedTagTypeException() { + super("The tag is not of the expected type"); + } + + public UnexpectedTagTypeException(String message) { + super(message); + } + + public UnexpectedTagTypeException(Throwable cause) { + super(cause); + } + + public UnexpectedTagTypeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/com/evilco/mc/nbt/stream/NbtInputStream.java b/src/com/evilco/mc/nbt/stream/NbtInputStream.java new file mode 100644 index 0000000..3ca56ba --- /dev/null +++ b/src/com/evilco/mc/nbt/stream/NbtInputStream.java @@ -0,0 +1,46 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.stream; + +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; + +public class NbtInputStream +extends DataInputStream { + public NbtInputStream(InputStream in) { + super(in); + } + + public ITag readTag() throws IOException { + byte type = this.readByte(); + TagType tagType = TagType.valueOf(type); + if (tagType == null) { + throw new IOException("Invalid NBT tag: Found unknown tag type " + type + "."); + } + if (tagType == TagType.END) { + return null; + } + return this.readTag(tagType, false); + } + + public ITag readTag(TagType type, boolean anonymous) throws IOException { + Constructor constructor = null; + try { + constructor = type.tagType.getConstructor(NbtInputStream.class, Boolean.TYPE); + } + catch (NoSuchMethodException ex) { + throw new IOException("Invalid NBT implementation state: Type " + type.tagType.getName() + " has no de-serialization constructor."); + } + try { + return constructor.newInstance(this, anonymous); + } + catch (Exception ex) { + throw new IOException("Invalid NBT implementation state: Type " + type.tagType.getName() + " in (" + this.getClass().getName() + ") has no valid constructor: " + ex.getMessage(), ex); + } + } +} diff --git a/src/com/evilco/mc/nbt/stream/NbtOutputStream.java b/src/com/evilco/mc/nbt/stream/NbtOutputStream.java new file mode 100644 index 0000000..38453e5 --- /dev/null +++ b/src/com/evilco/mc/nbt/stream/NbtOutputStream.java @@ -0,0 +1,21 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.stream; + +import com.evilco.mc.nbt.tag.ITag; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class NbtOutputStream +extends DataOutputStream { + public NbtOutputStream(OutputStream out) { + super(out); + } + + public void write(ITag tag) throws IOException { + this.writeByte(tag.getTagID()); + tag.write(this, false); + } +} diff --git a/src/com/evilco/mc/nbt/tag/AbstractTag.java b/src/com/evilco/mc/nbt/tag/AbstractTag.java new file mode 100644 index 0000000..22f122a --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/AbstractTag.java @@ -0,0 +1,86 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.IAnonymousTagContainer; +import com.evilco.mc.nbt.tag.INamedTagContainer; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.ITagContainer; +import com.google.common.base.Preconditions; +import java.io.IOException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class AbstractTag +implements ITag { + protected String name; + protected ITagContainer parent = null; + + public AbstractTag(@Nonnull String name) { + this.setName(name); + } + + public AbstractTag(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + Preconditions.checkNotNull(inputStream, "inputStream"); + if (!anonymous) { + short nameSize = inputStream.readShort(); + byte[] nameBytes = new byte[nameSize]; + inputStream.readFully(nameBytes); + this.setName(new String(nameBytes, STRING_CHARSET)); + } + } + + @Override + public String getName() { + return this.name; + } + + @Override + public byte[] getNameBytes() { + return this.name.getBytes(STRING_CHARSET); + } + + @Override + public ITagContainer getParent() { + return this.parent; + } + + @Override + public abstract byte getTagID(); + + @Override + public void setName(@Nonnull String name) { + Preconditions.checkNotNull(name, "name"); + if (this.getParent() != null) { + this.getParent().removeTag(this); + } + this.name = name; + if (this.getParent() != null) { + if (this.getParent() instanceof IAnonymousTagContainer) { + ((IAnonymousTagContainer)this.getParent()).addTag(this); + } else { + ((INamedTagContainer)this.getParent()).setTag(this); + } + } + } + + @Override + public void setParent(@Nullable ITagContainer parent) { + if (this.getParent() != null) { + this.getParent().removeTag(this); + } + this.parent = parent; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + if (!anonymous) { + byte[] name = this.getNameBytes(); + outputStream.writeShort(name.length); + outputStream.write(name); + } + } +} diff --git a/src/com/evilco/mc/nbt/tag/IAnonymousTagContainer.java b/src/com/evilco/mc/nbt/tag/IAnonymousTagContainer.java new file mode 100644 index 0000000..a3d3c95 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/IAnonymousTagContainer.java @@ -0,0 +1,21 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.error.UnexpectedTagTypeException; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.ITagContainer; +import java.util.List; +import javax.annotation.Nonnull; + +public interface IAnonymousTagContainer +extends ITagContainer { + public void addTag(@Nonnull ITag var1); + + public List getTags(); + + public List getTags(Class var1) throws UnexpectedTagTypeException; + + public void setTag(int var1, @Nonnull ITag var2); +} diff --git a/src/com/evilco/mc/nbt/tag/INamedTagContainer.java b/src/com/evilco/mc/nbt/tag/INamedTagContainer.java new file mode 100644 index 0000000..721e431 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/INamedTagContainer.java @@ -0,0 +1,24 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.error.TagNotFoundException; +import com.evilco.mc.nbt.error.UnexpectedTagTypeException; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.ITagContainer; +import java.util.Map; +import javax.annotation.Nonnull; + +public interface INamedTagContainer +extends ITagContainer { + public ITag getTag(@Nonnull String var1); + + public T getTag(String var1, Class var2) throws UnexpectedTagTypeException, TagNotFoundException; + + public Map getTags(); + + public void removeTag(@Nonnull String var1); + + public void setTag(@Nonnull ITag var1); +} diff --git a/src/com/evilco/mc/nbt/tag/ITag.java b/src/com/evilco/mc/nbt/tag/ITag.java new file mode 100644 index 0000000..fd80f40 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/ITag.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.ITagContainer; +import java.io.IOException; +import java.nio.charset.Charset; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface ITag { + public static final Charset STRING_CHARSET = Charset.forName("UTF-8"); + + public String getName(); + + public byte[] getNameBytes(); + + public ITagContainer getParent(); + + public byte getTagID(); + + public void setName(@Nonnull String var1); + + public void setParent(@Nullable ITagContainer var1); + + public void write(NbtOutputStream var1, boolean var2) throws IOException; +} diff --git a/src/com/evilco/mc/nbt/tag/ITagContainer.java b/src/com/evilco/mc/nbt/tag/ITagContainer.java new file mode 100644 index 0000000..f5d7d28 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/ITagContainer.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.tag.ITag; +import javax.annotation.Nonnull; + +public interface ITagContainer +extends ITag { + public void removeTag(@Nonnull ITag var1); +} diff --git a/src/com/evilco/mc/nbt/tag/TagByte.java b/src/com/evilco/mc/nbt/tag/TagByte.java new file mode 100644 index 0000000..9918ed0 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagByte.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagByte +extends AbstractTag { + protected byte value; + + public TagByte(@Nonnull String name, byte value) { + super(name); + this.setValue(value); + } + + public TagByte(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readByte()); + } + + @Override + public byte getTagID() { + return TagType.BYTE.typeID; + } + + public byte getValue() { + return this.value; + } + + public void setValue(byte b) { + this.value = b; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.write(this.getValue()); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagByteArray.java b/src/com/evilco/mc/nbt/tag/TagByteArray.java new file mode 100644 index 0000000..2832e96 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagByteArray.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import com.google.common.base.Preconditions; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagByteArray +extends AbstractTag { + protected byte[] value; + + public TagByteArray(@Nonnull String name, @Nonnull byte[] value) { + super(name); + this.setValue(value); + } + + public TagByteArray(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + int size = inputStream.readInt(); + byte[] data = new byte[size]; + inputStream.readFully(data); + this.setValue(data); + } + + @Override + public byte getTagID() { + return TagType.BYTE_ARRAY.typeID; + } + + public byte[] getValue() { + return this.value; + } + + public void setValue(@Nonnull byte[] b) { + Preconditions.checkNotNull(b, "b"); + this.value = b; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeInt(this.value.length); + outputStream.write(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagCompound.java b/src/com/evilco/mc/nbt/tag/TagCompound.java new file mode 100644 index 0000000..63d70c0 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagCompound.java @@ -0,0 +1,184 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.error.TagNotFoundException; +import com.evilco.mc.nbt.error.UnexpectedTagTypeException; +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.INamedTagContainer; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.TagByte; +import com.evilco.mc.nbt.tag.TagByteArray; +import com.evilco.mc.nbt.tag.TagDouble; +import com.evilco.mc.nbt.tag.TagFloat; +import com.evilco.mc.nbt.tag.TagInteger; +import com.evilco.mc.nbt.tag.TagIntegerArray; +import com.evilco.mc.nbt.tag.TagList; +import com.evilco.mc.nbt.tag.TagLong; +import com.evilco.mc.nbt.tag.TagShort; +import com.evilco.mc.nbt.tag.TagString; +import com.evilco.mc.nbt.tag.TagType; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; + +public class TagCompound +extends AbstractTag +implements INamedTagContainer { + protected Map tags = new HashMap(); + + public TagCompound(String name) { + super(name); + } + + public TagCompound(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + while (true) { + byte type; + TagType tagType; + if ((tagType = TagType.valueOf(type = inputStream.readByte())) == null) { + throw new IOException("Could not find a tag for type ID " + type + "."); + } + if (tagType == TagType.END) break; + this.setTag(inputStream.readTag(tagType, false)); + } + } + + @Override + public ITag getTag(@Nonnull String name) { + Preconditions.checkNotNull(name, "name"); + return this.tags.get(name); + } + + @Override + public T getTag(String name, Class tagClass) throws UnexpectedTagTypeException, TagNotFoundException { + ITag tag = this.getTag(name); + if (tag == null) { + throw new TagNotFoundException("The compound tag is missing a " + name + " entry"); + } + if (!tagClass.isInstance(tag)) { + throw new UnexpectedTagTypeException("The compound entry " + name + " should be of type " + tagClass.getSimpleName() + ", but is of type " + tag.getClass().getSimpleName()); + } + return (T)tag; + } + + public TagCompound getCompound(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagCompound.class); + } + + public int getInteger(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagInteger.class).getValue(); + } + + public short getShort(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagShort.class).getValue(); + } + + public byte getByte(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagByte.class).getValue(); + } + + public long getLong(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagLong.class).getValue(); + } + + public double getDouble(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagDouble.class).getValue(); + } + + public float getFloat(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagFloat.class).getValue(); + } + + public String getString(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagString.class).getValue(); + } + + public List getList(String name, Class itemClass) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagList.class).getTags(itemClass); + } + + public int[] getIntegerArray(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagIntegerArray.class).getValues(); + } + + public byte[] getByteArray(String name) throws UnexpectedTagTypeException, TagNotFoundException { + return this.getTag(name, TagByteArray.class).getValue(); + } + + public String[] getStringArray(String name) throws UnexpectedTagTypeException, TagNotFoundException { + List tags = this.getList(name, TagString.class); + String[] array = new String[tags.size()]; + for (int i = 0; i < tags.size(); ++i) { + array[i] = tags.get(i).getValue(); + } + return array; + } + + public double[] getDoubleArray(String name) throws UnexpectedTagTypeException, TagNotFoundException { + List tags = this.getList(name, TagDouble.class); + double[] array = new double[tags.size()]; + for (int i = 0; i < tags.size(); ++i) { + array[i] = tags.get(i).getValue(); + } + return array; + } + + public float[] getFloatArray(String name) throws UnexpectedTagTypeException, TagNotFoundException { + List tags = this.getList(name, TagFloat.class); + float[] array = new float[tags.size()]; + for (int i = 0; i < tags.size(); ++i) { + array[i] = tags.get(i).getValue(); + } + return array; + } + + @Override + public Map getTags() { + return new ImmutableMap.Builder().putAll(this.tags).build(); + } + + @Override + public void removeTag(@Nonnull ITag tag) { + Preconditions.checkNotNull(tag, "tag"); + this.tags.remove(tag.getName()); + } + + @Override + public void removeTag(@Nonnull String tag) { + Preconditions.checkNotNull(tag, "tag"); + this.tags.remove(tag); + } + + @Override + public void setTag(@Nonnull ITag tag) { + Preconditions.checkNotNull(tag, "tag"); + if (this.tags.containsKey(tag)) { + this.tags.get(tag.getName()).setParent(null); + } + this.tags.put(tag.getName(), tag); + tag.setParent(this); + } + + @Override + public byte getTagID() { + return TagType.COMPOUND.typeID; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + for (Map.Entry tagEntry : this.tags.entrySet()) { + outputStream.writeByte(tagEntry.getValue().getTagID()); + tagEntry.getValue().write(outputStream, false); + } + outputStream.writeByte(TagType.END.typeID); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagDouble.java b/src/com/evilco/mc/nbt/tag/TagDouble.java new file mode 100644 index 0000000..a6115ad --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagDouble.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagDouble +extends AbstractTag { + protected double value; + + public TagDouble(@Nonnull String name, double value) { + super(name); + this.setValue(value); + } + + public TagDouble(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readDouble()); + } + + @Override + public byte getTagID() { + return TagType.DOUBLE.typeID; + } + + public double getValue() { + return this.value; + } + + public void setValue(double d) { + this.value = d; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeDouble(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagFloat.java b/src/com/evilco/mc/nbt/tag/TagFloat.java new file mode 100644 index 0000000..21f21b4 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagFloat.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagFloat +extends AbstractTag { + protected float value; + + public TagFloat(@Nonnull String name, float value) { + super(name); + this.setValue(value); + } + + public TagFloat(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readFloat()); + } + + @Override + public byte getTagID() { + return TagType.FLOAT.typeID; + } + + public float getValue() { + return this.value; + } + + public void setValue(float f) { + this.value = f; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeFloat(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagInteger.java b/src/com/evilco/mc/nbt/tag/TagInteger.java new file mode 100644 index 0000000..7b3b4d0 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagInteger.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagInteger +extends AbstractTag { + protected int value; + + public TagInteger(@Nonnull String name, int value) { + super(name); + this.setValue(value); + } + + public TagInteger(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readInt()); + } + + @Override + public byte getTagID() { + return TagType.INTEGER.typeID; + } + + public int getValue() { + return this.value; + } + + public void setValue(int i) { + this.value = i; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeInt(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagIntegerArray.java b/src/com/evilco/mc/nbt/tag/TagIntegerArray.java new file mode 100644 index 0000000..144d070 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagIntegerArray.java @@ -0,0 +1,55 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import com.google.common.base.Preconditions; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagIntegerArray +extends AbstractTag { + protected int[] values; + + public TagIntegerArray(@Nonnull String name, @Nonnull int[] values) { + super(name); + this.setValues(values); + } + + public TagIntegerArray(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + int size = inputStream.readInt(); + int[] data = new int[size]; + for (int i = 0; i < size; ++i) { + data[i] = inputStream.readInt(); + } + this.values = data; + } + + @Override + public byte getTagID() { + return TagType.INTEGER_ARRAY.typeID; + } + + public int[] getValues() { + return this.values; + } + + public void setValues(@Nonnull int[] i) { + Preconditions.checkNotNull(i, "i"); + this.values = i; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeInt(this.values.length); + for (int i : this.values) { + outputStream.writeInt(i); + } + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagList.java b/src/com/evilco/mc/nbt/tag/TagList.java new file mode 100644 index 0000000..f8fdb1e --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagList.java @@ -0,0 +1,96 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.error.UnexpectedTagTypeException; +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.IAnonymousTagContainer; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.TagType; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; + +public class TagList +extends AbstractTag +implements IAnonymousTagContainer { + protected List tagList; + + public TagList(@Nonnull String name) { + super(name); + this.tagList = new ArrayList(); + } + + public TagList(@Nonnull String name, @Nonnull List tagList) { + super(name); + Preconditions.checkNotNull(tagList, "tagList"); + this.tagList = tagList; + } + + public TagList(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.tagList = new ArrayList(); + byte type = inputStream.readByte(); + TagType tagType = TagType.valueOf(type); + int size = inputStream.readInt(); + if (tagType == TagType.END) { + return; + } + for (int i = 0; i < size; ++i) { + this.addTag(inputStream.readTag(tagType, true)); + } + } + + @Override + public void addTag(@Nonnull ITag tag) { + this.tagList.add(tag); + } + + @Override + public List getTags() { + return ((ImmutableList.Builder)new ImmutableList.Builder().addAll(this.tagList)).build(); + } + + @Override + public List getTags(Class tagClass) throws UnexpectedTagTypeException { + ImmutableList.Builder builder = new ImmutableList.Builder(); + for (ITag tag : this.tagList) { + if (!tagClass.isInstance(tag)) { + throw new UnexpectedTagTypeException("The list entry should be of type " + tagClass.getSimpleName() + ", but is of type " + tag.getClass().getSimpleName()); + } + builder.add(tag); + } + return builder.build(); + } + + @Override + public byte getTagID() { + return TagType.LIST.typeID; + } + + @Override + public void removeTag(@Nonnull ITag tag) { + this.tagList.remove(tag); + } + + @Override + public void setTag(int i, @Nonnull ITag tag) { + this.tagList.set(i, tag); + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeByte(this.tagList.size() > 0 ? this.tagList.get(0).getTagID() : TagType.END.typeID); + outputStream.writeInt(this.tagList.size()); + for (ITag tag : this.tagList) { + tag.write(outputStream, true); + } + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagLong.java b/src/com/evilco/mc/nbt/tag/TagLong.java new file mode 100644 index 0000000..8b07454 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagLong.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagLong +extends AbstractTag { + protected long value; + + public TagLong(@Nonnull String name, long value) { + super(name); + this.setValue(value); + } + + public TagLong(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readLong()); + } + + @Override + public byte getTagID() { + return TagType.LONG.typeID; + } + + public long getValue() { + return this.value; + } + + public void setValue(long l) { + this.value = l; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeLong(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagShort.java b/src/com/evilco/mc/nbt/tag/TagShort.java new file mode 100644 index 0000000..8e7cc65 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagShort.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagShort +extends AbstractTag { + protected short value; + + public TagShort(@Nonnull String name, short value) { + super(name); + this.setValue(value); + } + + public TagShort(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + this.setValue(inputStream.readShort()); + } + + @Override + public byte getTagID() { + return TagType.SHORT.typeID; + } + + public short getValue() { + return this.value; + } + + public void setValue(short s) { + this.value = s; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + outputStream.writeShort(this.value); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagString.java b/src/com/evilco/mc/nbt/tag/TagString.java new file mode 100644 index 0000000..5cd53b8 --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagString.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.stream.NbtInputStream; +import com.evilco.mc.nbt.stream.NbtOutputStream; +import com.evilco.mc.nbt.tag.AbstractTag; +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.TagType; +import java.io.IOException; +import javax.annotation.Nonnull; + +public class TagString +extends AbstractTag { + protected String value; + + public TagString(@Nonnull String name, @Nonnull String value) { + super(name); + this.setValue(value); + } + + public TagString(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException { + super(inputStream, anonymous); + short size = inputStream.readShort(); + byte[] data = new byte[size]; + inputStream.readFully(data); + this.setValue(new String(data, ITag.STRING_CHARSET)); + } + + @Override + public byte getTagID() { + return TagType.STRING.typeID; + } + + public String getValue() { + return this.value; + } + + public void setValue(@Nonnull String s) { + this.value = s; + } + + @Override + public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException { + super.write(outputStream, anonymous); + byte[] outputBytes = this.value.getBytes(ITag.STRING_CHARSET); + outputStream.writeShort(outputBytes.length); + outputStream.write(outputBytes); + } +} diff --git a/src/com/evilco/mc/nbt/tag/TagType.java b/src/com/evilco/mc/nbt/tag/TagType.java new file mode 100644 index 0000000..f48e16c --- /dev/null +++ b/src/com/evilco/mc/nbt/tag/TagType.java @@ -0,0 +1,55 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.evilco.mc.nbt.tag; + +import com.evilco.mc.nbt.tag.ITag; +import com.evilco.mc.nbt.tag.TagByte; +import com.evilco.mc.nbt.tag.TagByteArray; +import com.evilco.mc.nbt.tag.TagCompound; +import com.evilco.mc.nbt.tag.TagDouble; +import com.evilco.mc.nbt.tag.TagFloat; +import com.evilco.mc.nbt.tag.TagInteger; +import com.evilco.mc.nbt.tag.TagIntegerArray; +import com.evilco.mc.nbt.tag.TagList; +import com.evilco.mc.nbt.tag.TagLong; +import com.evilco.mc.nbt.tag.TagShort; +import com.evilco.mc.nbt.tag.TagString; +import com.google.common.collect.ImmutableMap; +import java.util.Map; + +public enum TagType { + BYTE(1, TagByte.class), + BYTE_ARRAY(7, TagByteArray.class), + COMPOUND(10, TagCompound.class), + DOUBLE(6, TagDouble.class), + END(0, null), + FLOAT(5, TagFloat.class), + INTEGER(3, TagInteger.class), + INTEGER_ARRAY(11, TagIntegerArray.class), + LIST(9, TagList.class), + LONG(4, TagLong.class), + SHORT(2, TagShort.class), + STRING(8, TagString.class); + + protected static final Map typeMap; + public final Class tagType; + public final byte typeID; + + private TagType(int typeID, Class type) { + this.typeID = (byte)typeID; + this.tagType = type; + } + + public static TagType valueOf(byte typeID) { + return typeMap.get(typeID); + } + + static { + ImmutableMap.Builder mapBuilder = new ImmutableMap.Builder(); + for (TagType type : TagType.values()) { + mapBuilder.put(type.typeID, type); + } + typeMap = mapBuilder.build(); + } +} diff --git a/src/com/google/common/annotations/Beta.java b/src/com/google/common/annotations/Beta.java new file mode 100644 index 0000000..064de6e --- /dev/null +++ b/src/com/google/common/annotations/Beta.java @@ -0,0 +1,18 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.annotations; + +import com.google.common.annotations.GwtCompatible; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.CLASS) +@Target(value={ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) +@Documented +@GwtCompatible +public @interface Beta { +} diff --git a/src/com/google/common/annotations/GwtCompatible.java b/src/com/google/common/annotations/GwtCompatible.java new file mode 100644 index 0000000..ca088f1 --- /dev/null +++ b/src/com/google/common/annotations/GwtCompatible.java @@ -0,0 +1,20 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.CLASS) +@Target(value={ElementType.TYPE, ElementType.METHOD}) +@Documented +@GwtCompatible +public @interface GwtCompatible { + public boolean serializable() default false; + + public boolean emulated() default false; +} diff --git a/src/com/google/common/annotations/GwtIncompatible.java b/src/com/google/common/annotations/GwtIncompatible.java new file mode 100644 index 0000000..460ae87 --- /dev/null +++ b/src/com/google/common/annotations/GwtIncompatible.java @@ -0,0 +1,19 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.annotations; + +import com.google.common.annotations.GwtCompatible; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.CLASS) +@Target(value={ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) +@Documented +@GwtCompatible +public @interface GwtIncompatible { + public String value(); +} diff --git a/src/com/google/common/annotations/VisibleForTesting.java b/src/com/google/common/annotations/VisibleForTesting.java new file mode 100644 index 0000000..9fa66e5 --- /dev/null +++ b/src/com/google/common/annotations/VisibleForTesting.java @@ -0,0 +1,10 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.annotations; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public @interface VisibleForTesting { +} diff --git a/src/com/google/common/base/Absent.java b/src/com/google/common/base/Absent.java new file mode 100644 index 0000000..5dd1c74 --- /dev/null +++ b/src/com/google/common/base/Absent.java @@ -0,0 +1,88 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.Collections; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +final class Absent +extends Optional { + static final Absent INSTANCE = new Absent(); + private static final long serialVersionUID = 0L; + + static Optional withType() { + return INSTANCE; + } + + private Absent() { + } + + @Override + public boolean isPresent() { + return false; + } + + @Override + public T get() { + throw new IllegalStateException("Optional.get() cannot be called on an absent value"); + } + + @Override + public T or(T defaultValue) { + return Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)"); + } + + @Override + public Optional or(Optional secondChoice) { + return Preconditions.checkNotNull(secondChoice); + } + + @Override + public T or(Supplier supplier) { + return Preconditions.checkNotNull(supplier.get(), "use Optional.orNull() instead of a Supplier that returns null"); + } + + @Override + @Nullable + public T orNull() { + return null; + } + + @Override + public Set asSet() { + return Collections.emptySet(); + } + + @Override + public Optional transform(Function function) { + Preconditions.checkNotNull(function); + return Optional.absent(); + } + + @Override + public boolean equals(@Nullable Object object) { + return object == this; + } + + @Override + public int hashCode() { + return 1502476572; + } + + @Override + public String toString() { + return "Optional.absent()"; + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/com/google/common/base/AbstractIterator.java b/src/com/google/common/base/AbstractIterator.java new file mode 100644 index 0000000..a97aebe --- /dev/null +++ b/src/com/google/common/base/AbstractIterator.java @@ -0,0 +1,74 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Iterator; +import java.util.NoSuchElementException; + +@GwtCompatible +abstract class AbstractIterator +implements Iterator { + private State state = State.NOT_READY; + private T next; + + protected AbstractIterator() { + } + + protected abstract T computeNext(); + + protected final T endOfData() { + this.state = State.DONE; + return null; + } + + @Override + public final boolean hasNext() { + Preconditions.checkState(this.state != State.FAILED); + switch (this.state) { + case DONE: { + return false; + } + case READY: { + return true; + } + } + return this.tryToComputeNext(); + } + + private boolean tryToComputeNext() { + this.state = State.FAILED; + this.next = this.computeNext(); + if (this.state != State.DONE) { + this.state = State.READY; + return true; + } + return false; + } + + @Override + public final T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.state = State.NOT_READY; + T result = this.next; + this.next = null; + return result; + } + + @Override + public final void remove() { + throw new UnsupportedOperationException(); + } + + private static enum State { + READY, + NOT_READY, + DONE, + FAILED; + + } +} diff --git a/src/com/google/common/base/Ascii.java b/src/com/google/common/base/Ascii.java new file mode 100644 index 0000000..7637184 --- /dev/null +++ b/src/com/google/common/base/Ascii.java @@ -0,0 +1,169 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import javax.annotation.CheckReturnValue; + +@GwtCompatible +public final class Ascii { + public static final byte NUL = 0; + public static final byte SOH = 1; + public static final byte STX = 2; + public static final byte ETX = 3; + public static final byte EOT = 4; + public static final byte ENQ = 5; + public static final byte ACK = 6; + public static final byte BEL = 7; + public static final byte BS = 8; + public static final byte HT = 9; + public static final byte LF = 10; + public static final byte NL = 10; + public static final byte VT = 11; + public static final byte FF = 12; + public static final byte CR = 13; + public static final byte SO = 14; + public static final byte SI = 15; + public static final byte DLE = 16; + public static final byte DC1 = 17; + public static final byte XON = 17; + public static final byte DC2 = 18; + public static final byte DC3 = 19; + public static final byte XOFF = 19; + public static final byte DC4 = 20; + public static final byte NAK = 21; + public static final byte SYN = 22; + public static final byte ETB = 23; + public static final byte CAN = 24; + public static final byte EM = 25; + public static final byte SUB = 26; + public static final byte ESC = 27; + public static final byte FS = 28; + public static final byte GS = 29; + public static final byte RS = 30; + public static final byte US = 31; + public static final byte SP = 32; + public static final byte SPACE = 32; + public static final byte DEL = 127; + public static final char MIN = '\u0000'; + public static final char MAX = '\u007f'; + + private Ascii() { + } + + public static String toLowerCase(String string) { + int length = string.length(); + for (int i = 0; i < length; ++i) { + if (!Ascii.isUpperCase(string.charAt(i))) continue; + char[] chars = string.toCharArray(); + while (i < length) { + char c = chars[i]; + if (Ascii.isUpperCase(c)) { + chars[i] = (char)(c ^ 0x20); + } + ++i; + } + return String.valueOf(chars); + } + return string; + } + + public static String toLowerCase(CharSequence chars) { + if (chars instanceof String) { + return Ascii.toLowerCase((String)chars); + } + int length = chars.length(); + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + builder.append(Ascii.toLowerCase(chars.charAt(i))); + } + return builder.toString(); + } + + public static char toLowerCase(char c) { + return Ascii.isUpperCase(c) ? (char)(c ^ 0x20) : c; + } + + public static String toUpperCase(String string) { + int length = string.length(); + for (int i = 0; i < length; ++i) { + if (!Ascii.isLowerCase(string.charAt(i))) continue; + char[] chars = string.toCharArray(); + while (i < length) { + char c = chars[i]; + if (Ascii.isLowerCase(c)) { + chars[i] = (char)(c & 0x5F); + } + ++i; + } + return String.valueOf(chars); + } + return string; + } + + public static String toUpperCase(CharSequence chars) { + if (chars instanceof String) { + return Ascii.toUpperCase((String)chars); + } + int length = chars.length(); + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + builder.append(Ascii.toUpperCase(chars.charAt(i))); + } + return builder.toString(); + } + + public static char toUpperCase(char c) { + return Ascii.isLowerCase(c) ? (char)(c & 0x5F) : c; + } + + public static boolean isLowerCase(char c) { + return c >= 'a' && c <= 'z'; + } + + public static boolean isUpperCase(char c) { + return c >= 'A' && c <= 'Z'; + } + + @CheckReturnValue + @Beta + public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) { + Preconditions.checkNotNull(seq); + int truncationLength = maxLength - truncationIndicator.length(); + Preconditions.checkArgument(truncationLength >= 0, "maxLength (%s) must be >= length of the truncation indicator (%s)", maxLength, truncationIndicator.length()); + if (seq.length() <= maxLength) { + String string = seq.toString(); + if (string.length() <= maxLength) { + return string; + } + seq = string; + } + return new StringBuilder(maxLength).append(seq, 0, truncationLength).append(truncationIndicator).toString(); + } + + @Beta + public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) { + int length = s1.length(); + if (s1 == s2) { + return true; + } + if (length != s2.length()) { + return false; + } + for (int i = 0; i < length; ++i) { + int alphaIndex; + char c2; + char c1 = s1.charAt(i); + if (c1 == (c2 = s2.charAt(i)) || (alphaIndex = Ascii.getAlphaIndex(c1)) < 26 && alphaIndex == Ascii.getAlphaIndex(c2)) continue; + return false; + } + return true; + } + + private static int getAlphaIndex(char c) { + return (char)((c | 0x20) - 97); + } +} diff --git a/src/com/google/common/base/CaseFormat.java b/src/com/google/common/base/CaseFormat.java new file mode 100644 index 0000000..0ef48f8 --- /dev/null +++ b/src/com/google/common/base/CaseFormat.java @@ -0,0 +1,179 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible +public enum CaseFormat { + LOWER_HYPHEN(CharMatcher.is('-'), "-"){ + + @Override + String normalizeWord(String word) { + return Ascii.toLowerCase(word); + } + + @Override + String convert(CaseFormat format, String s) { + if (format == LOWER_UNDERSCORE) { + return s.replace('-', '_'); + } + if (format == UPPER_UNDERSCORE) { + return Ascii.toUpperCase(s.replace('-', '_')); + } + return super.convert(format, s); + } + } + , + LOWER_UNDERSCORE(CharMatcher.is('_'), "_"){ + + @Override + String normalizeWord(String word) { + return Ascii.toLowerCase(word); + } + + @Override + String convert(CaseFormat format, String s) { + if (format == LOWER_HYPHEN) { + return s.replace('_', '-'); + } + if (format == UPPER_UNDERSCORE) { + return Ascii.toUpperCase(s); + } + return super.convert(format, s); + } + } + , + LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), ""){ + + @Override + String normalizeWord(String word) { + return CaseFormat.firstCharOnlyToUpper(word); + } + } + , + UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), ""){ + + @Override + String normalizeWord(String word) { + return CaseFormat.firstCharOnlyToUpper(word); + } + } + , + UPPER_UNDERSCORE(CharMatcher.is('_'), "_"){ + + @Override + String normalizeWord(String word) { + return Ascii.toUpperCase(word); + } + + @Override + String convert(CaseFormat format, String s) { + if (format == LOWER_HYPHEN) { + return Ascii.toLowerCase(s.replace('_', '-')); + } + if (format == LOWER_UNDERSCORE) { + return Ascii.toLowerCase(s); + } + return super.convert(format, s); + } + }; + + private final CharMatcher wordBoundary; + private final String wordSeparator; + + private CaseFormat(CharMatcher wordBoundary, String wordSeparator) { + this.wordBoundary = wordBoundary; + this.wordSeparator = wordSeparator; + } + + public final String to(CaseFormat format, String str) { + Preconditions.checkNotNull(format); + Preconditions.checkNotNull(str); + return format == this ? str : this.convert(format, str); + } + + String convert(CaseFormat format, String s) { + StringBuilder out = null; + int i = 0; + int j = -1; + while (true) { + ++j; + if ((j = this.wordBoundary.indexIn(s, j)) == -1) break; + if (i == 0) { + out = new StringBuilder(s.length() + 4 * this.wordSeparator.length()); + out.append(format.normalizeFirstWord(s.substring(i, j))); + } else { + out.append(format.normalizeWord(s.substring(i, j))); + } + out.append(format.wordSeparator); + i = j + this.wordSeparator.length(); + } + return i == 0 ? format.normalizeFirstWord(s) : out.append(format.normalizeWord(s.substring(i))).toString(); + } + + @Beta + public Converter converterTo(CaseFormat targetFormat) { + return new StringConverter(this, targetFormat); + } + + abstract String normalizeWord(String var1); + + private String normalizeFirstWord(String word) { + return this == LOWER_CAMEL ? Ascii.toLowerCase(word) : this.normalizeWord(word); + } + + private static String firstCharOnlyToUpper(String word) { + return word.isEmpty() ? word : new StringBuilder(word.length()).append(Ascii.toUpperCase(word.charAt(0))).append(Ascii.toLowerCase(word.substring(1))).toString(); + } + + private static final class StringConverter + extends Converter + implements Serializable { + private final CaseFormat sourceFormat; + private final CaseFormat targetFormat; + private static final long serialVersionUID = 0L; + + StringConverter(CaseFormat sourceFormat, CaseFormat targetFormat) { + this.sourceFormat = Preconditions.checkNotNull(sourceFormat); + this.targetFormat = Preconditions.checkNotNull(targetFormat); + } + + @Override + protected String doForward(String s) { + return s == null ? null : this.sourceFormat.to(this.targetFormat, s); + } + + @Override + protected String doBackward(String s) { + return s == null ? null : this.targetFormat.to(this.sourceFormat, s); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof StringConverter) { + StringConverter that = (StringConverter)object; + return this.sourceFormat.equals((Object)that.sourceFormat) && this.targetFormat.equals((Object)that.targetFormat); + } + return false; + } + + public int hashCode() { + return this.sourceFormat.hashCode() ^ this.targetFormat.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf((Object)this.sourceFormat)); + String string2 = String.valueOf(String.valueOf((Object)this.targetFormat)); + return new StringBuilder(14 + string.length() + string2.length()).append(string).append(".converterTo(").append(string2).append(")").toString(); + } + } +} diff --git a/src/com/google/common/base/CharMatcher.java b/src/com/google/common/base/CharMatcher.java new file mode 100644 index 0000000..0ca24ae --- /dev/null +++ b/src/com/google/common/base/CharMatcher.java @@ -0,0 +1,1018 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Platform; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.SmallCharMatcher; +import java.util.Arrays; +import java.util.BitSet; +import javax.annotation.CheckReturnValue; + +@Beta +@GwtCompatible(emulated=true) +public abstract class CharMatcher +implements Predicate { + public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher(){ + + @Override + public boolean matches(char c) { + switch (c) { + case '\t': + case '\n': + case '\u000b': + case '\f': + case '\r': + case ' ': + case '\u0085': + case '\u1680': + case '\u2028': + case '\u2029': + case '\u205f': + case '\u3000': { + return true; + } + case '\u2007': { + return false; + } + } + return c >= '\u2000' && c <= '\u200a'; + } + + @Override + public String toString() { + return "CharMatcher.BREAKING_WHITESPACE"; + } + }; + public static final CharMatcher ASCII = CharMatcher.inRange('\u0000', '\u007f', "CharMatcher.ASCII"); + private static final String ZEROES = "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6\u0c66\u0ce6\u0d66\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1b50\u1bb0\u1c40\u1c50\ua620\ua8d0\ua900\uaa50\uff10"; + private static final String NINES; + public static final CharMatcher DIGIT; + public static final CharMatcher JAVA_DIGIT; + public static final CharMatcher JAVA_LETTER; + public static final CharMatcher JAVA_LETTER_OR_DIGIT; + public static final CharMatcher JAVA_UPPER_CASE; + public static final CharMatcher JAVA_LOWER_CASE; + public static final CharMatcher JAVA_ISO_CONTROL; + public static final CharMatcher INVISIBLE; + public static final CharMatcher SINGLE_WIDTH; + public static final CharMatcher ANY; + public static final CharMatcher NONE; + final String description; + private static final int DISTINCT_CHARS = 65536; + static final String WHITESPACE_TABLE = "\u2002\u3000\r\u0085\u200a\u2005\u2000\u3000\u2029\u000b\u3000\u2008\u2003\u205f\u3000\u1680\t \u2006\u2001\u202f\u00a0\f\u2009\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000"; + static final int WHITESPACE_MULTIPLIER = 1682554634; + static final int WHITESPACE_SHIFT; + public static final CharMatcher WHITESPACE; + + private static String showCharacter(char c) { + String hex = "0123456789ABCDEF"; + char[] tmp = new char[]{'\\', 'u', '\u0000', '\u0000', '\u0000', '\u0000'}; + for (int i = 0; i < 4; ++i) { + tmp[5 - i] = hex.charAt(c & 0xF); + c = (char)(c >> 4); + } + return String.copyValueOf(tmp); + } + + public static CharMatcher is(final char match) { + String string = String.valueOf(String.valueOf(CharMatcher.showCharacter(match))); + String description = new StringBuilder(18 + string.length()).append("CharMatcher.is('").append(string).append("')").toString(); + return new FastMatcher(description){ + + @Override + public boolean matches(char c) { + return c == match; + } + + @Override + public String replaceFrom(CharSequence sequence, char replacement) { + return sequence.toString().replace(match, replacement); + } + + @Override + public CharMatcher and(CharMatcher other) { + return other.matches(match) ? this : NONE; + } + + @Override + public CharMatcher or(CharMatcher other) { + return other.matches(match) ? other : super.or(other); + } + + @Override + public CharMatcher negate() { + return 9.isNot(match); + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + table.set(match); + } + }; + } + + public static CharMatcher isNot(final char match) { + String string = String.valueOf(String.valueOf(CharMatcher.showCharacter(match))); + String description = new StringBuilder(21 + string.length()).append("CharMatcher.isNot('").append(string).append("')").toString(); + return new FastMatcher(description){ + + @Override + public boolean matches(char c) { + return c != match; + } + + @Override + public CharMatcher and(CharMatcher other) { + return other.matches(match) ? super.and(other) : other; + } + + @Override + public CharMatcher or(CharMatcher other) { + return other.matches(match) ? ANY : this; + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + table.set(0, match); + table.set(match + '\u0001', 65536); + } + + @Override + public CharMatcher negate() { + return 10.is(match); + } + }; + } + + public static CharMatcher anyOf(CharSequence sequence) { + switch (sequence.length()) { + case 0: { + return NONE; + } + case 1: { + return CharMatcher.is(sequence.charAt(0)); + } + case 2: { + return CharMatcher.isEither(sequence.charAt(0), sequence.charAt(1)); + } + } + final char[] chars = sequence.toString().toCharArray(); + Arrays.sort(chars); + StringBuilder description = new StringBuilder("CharMatcher.anyOf(\""); + for (char c : chars) { + description.append(CharMatcher.showCharacter(c)); + } + description.append("\")"); + return new CharMatcher(description.toString()){ + + @Override + public boolean matches(char c) { + return Arrays.binarySearch(chars, c) >= 0; + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + for (char c : chars) { + table.set(c); + } + } + }; + } + + private static CharMatcher isEither(final char match1, final char match2) { + String string = String.valueOf(String.valueOf(CharMatcher.showCharacter(match1))); + String string2 = String.valueOf(String.valueOf(CharMatcher.showCharacter(match2))); + String description = new StringBuilder(21 + string.length() + string2.length()).append("CharMatcher.anyOf(\"").append(string).append(string2).append("\")").toString(); + return new FastMatcher(description){ + + @Override + public boolean matches(char c) { + return c == match1 || c == match2; + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + table.set(match1); + table.set(match2); + } + }; + } + + public static CharMatcher noneOf(CharSequence sequence) { + return CharMatcher.anyOf(sequence).negate(); + } + + public static CharMatcher inRange(char startInclusive, char endInclusive) { + Preconditions.checkArgument(endInclusive >= startInclusive); + String string = String.valueOf(String.valueOf(CharMatcher.showCharacter(startInclusive))); + String string2 = String.valueOf(String.valueOf(CharMatcher.showCharacter(endInclusive))); + String description = new StringBuilder(27 + string.length() + string2.length()).append("CharMatcher.inRange('").append(string).append("', '").append(string2).append("')").toString(); + return CharMatcher.inRange(startInclusive, endInclusive, description); + } + + static CharMatcher inRange(final char startInclusive, final char endInclusive, String description) { + return new FastMatcher(description){ + + @Override + public boolean matches(char c) { + return startInclusive <= c && c <= endInclusive; + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + table.set((int)startInclusive, endInclusive + '\u0001'); + } + }; + } + + public static CharMatcher forPredicate(final Predicate predicate) { + Preconditions.checkNotNull(predicate); + if (predicate instanceof CharMatcher) { + return (CharMatcher)predicate; + } + String string = String.valueOf(String.valueOf(predicate)); + String description = new StringBuilder(26 + string.length()).append("CharMatcher.forPredicate(").append(string).append(")").toString(); + return new CharMatcher(description){ + + @Override + public boolean matches(char c) { + return predicate.apply(Character.valueOf(c)); + } + + @Override + public boolean apply(Character character) { + return predicate.apply(Preconditions.checkNotNull(character)); + } + }; + } + + CharMatcher(String description) { + this.description = description; + } + + protected CharMatcher() { + this.description = super.toString(); + } + + public abstract boolean matches(char var1); + + public CharMatcher negate() { + return new NegatedMatcher(this); + } + + public CharMatcher and(CharMatcher other) { + return new And(this, Preconditions.checkNotNull(other)); + } + + public CharMatcher or(CharMatcher other) { + return new Or(this, Preconditions.checkNotNull(other)); + } + + public CharMatcher precomputed() { + return Platform.precomputeCharMatcher(this); + } + + CharMatcher withToString(String description) { + throw new UnsupportedOperationException(); + } + + @GwtIncompatible(value="java.util.BitSet") + CharMatcher precomputedInternal() { + String string; + BitSet table = new BitSet(); + this.setBits(table); + int totalCharacters = table.cardinality(); + if (totalCharacters * 2 <= 65536) { + return CharMatcher.precomputedPositive(totalCharacters, table, this.description); + } + table.flip(0, 65536); + int negatedCharacters = 65536 - totalCharacters; + String suffix = ".negate()"; + if (this.description.endsWith(suffix)) { + string = this.description.substring(0, this.description.length() - suffix.length()); + } else { + String string2 = String.valueOf(this.description); + String string3 = String.valueOf(suffix); + string = string3.length() != 0 ? string2.concat(string3) : new String(string2); + } + String negatedDescription = string; + return new NegatedFastMatcher(this.toString(), CharMatcher.precomputedPositive(negatedCharacters, table, negatedDescription)); + } + + @GwtIncompatible(value="java.util.BitSet") + private static CharMatcher precomputedPositive(int totalCharacters, BitSet table, String description) { + switch (totalCharacters) { + case 0: { + return NONE; + } + case 1: { + return CharMatcher.is((char)table.nextSetBit(0)); + } + case 2: { + char c1 = (char)table.nextSetBit(0); + char c2 = (char)table.nextSetBit(c1 + '\u0001'); + return CharMatcher.isEither(c1, c2); + } + } + return CharMatcher.isSmall(totalCharacters, table.length()) ? SmallCharMatcher.from(table, description) : new BitSetMatcher(table, description); + } + + @GwtIncompatible(value="SmallCharMatcher") + private static boolean isSmall(int totalCharacters, int tableLength) { + return totalCharacters <= 1023 && tableLength > totalCharacters * 4 * 16; + } + + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + for (int c = 65535; c >= 0; --c) { + if (!this.matches((char)c)) continue; + table.set(c); + } + } + + public boolean matchesAnyOf(CharSequence sequence) { + return !this.matchesNoneOf(sequence); + } + + public boolean matchesAllOf(CharSequence sequence) { + for (int i = sequence.length() - 1; i >= 0; --i) { + if (this.matches(sequence.charAt(i))) continue; + return false; + } + return true; + } + + public boolean matchesNoneOf(CharSequence sequence) { + return this.indexIn(sequence) == -1; + } + + public int indexIn(CharSequence sequence) { + int length = sequence.length(); + for (int i = 0; i < length; ++i) { + if (!this.matches(sequence.charAt(i))) continue; + return i; + } + return -1; + } + + public int indexIn(CharSequence sequence, int start) { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + for (int i = start; i < length; ++i) { + if (!this.matches(sequence.charAt(i))) continue; + return i; + } + return -1; + } + + public int lastIndexIn(CharSequence sequence) { + for (int i = sequence.length() - 1; i >= 0; --i) { + if (!this.matches(sequence.charAt(i))) continue; + return i; + } + return -1; + } + + public int countIn(CharSequence sequence) { + int count = 0; + for (int i = 0; i < sequence.length(); ++i) { + if (!this.matches(sequence.charAt(i))) continue; + ++count; + } + return count; + } + + @CheckReturnValue + public String removeFrom(CharSequence sequence) { + String string = sequence.toString(); + int pos = this.indexIn(string); + if (pos == -1) { + return string; + } + char[] chars = string.toCharArray(); + int spread = 1; + block0: while (true) { + ++pos; + while (pos != chars.length) { + if (!this.matches(chars[pos])) { + chars[pos - spread] = chars[pos]; + ++pos; + continue; + } + ++spread; + continue block0; + } + break; + } + return new String(chars, 0, pos - spread); + } + + @CheckReturnValue + public String retainFrom(CharSequence sequence) { + return this.negate().removeFrom(sequence); + } + + @CheckReturnValue + public String replaceFrom(CharSequence sequence, char replacement) { + String string = sequence.toString(); + int pos = this.indexIn(string); + if (pos == -1) { + return string; + } + char[] chars = string.toCharArray(); + chars[pos] = replacement; + for (int i = pos + 1; i < chars.length; ++i) { + if (!this.matches(chars[i])) continue; + chars[i] = replacement; + } + return new String(chars); + } + + @CheckReturnValue + public String replaceFrom(CharSequence sequence, CharSequence replacement) { + int replacementLen = replacement.length(); + if (replacementLen == 0) { + return this.removeFrom(sequence); + } + if (replacementLen == 1) { + return this.replaceFrom(sequence, replacement.charAt(0)); + } + String string = sequence.toString(); + int pos = this.indexIn(string); + if (pos == -1) { + return string; + } + int len = string.length(); + StringBuilder buf = new StringBuilder(len * 3 / 2 + 16); + int oldpos = 0; + do { + buf.append(string, oldpos, pos); + buf.append(replacement); + } while ((pos = this.indexIn(string, oldpos = pos + 1)) != -1); + buf.append(string, oldpos, len); + return buf.toString(); + } + + @CheckReturnValue + public String trimFrom(CharSequence sequence) { + int last; + int first; + int len = sequence.length(); + for (first = 0; first < len && this.matches(sequence.charAt(first)); ++first) { + } + for (last = len - 1; last > first && this.matches(sequence.charAt(last)); --last) { + } + return sequence.subSequence(first, last + 1).toString(); + } + + @CheckReturnValue + public String trimLeadingFrom(CharSequence sequence) { + int len = sequence.length(); + for (int first = 0; first < len; ++first) { + if (this.matches(sequence.charAt(first))) continue; + return sequence.subSequence(first, len).toString(); + } + return ""; + } + + @CheckReturnValue + public String trimTrailingFrom(CharSequence sequence) { + int len = sequence.length(); + for (int last = len - 1; last >= 0; --last) { + if (this.matches(sequence.charAt(last))) continue; + return sequence.subSequence(0, last + 1).toString(); + } + return ""; + } + + @CheckReturnValue + public String collapseFrom(CharSequence sequence, char replacement) { + int len = sequence.length(); + for (int i = 0; i < len; ++i) { + char c = sequence.charAt(i); + if (!this.matches(c)) continue; + if (!(c != replacement || i != len - 1 && this.matches(sequence.charAt(i + 1)))) { + ++i; + continue; + } + StringBuilder builder = new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement); + return this.finishCollapseFrom(sequence, i + 1, len, replacement, builder, true); + } + return sequence.toString(); + } + + @CheckReturnValue + public String trimAndCollapseFrom(CharSequence sequence, char replacement) { + int last; + int first; + int len = sequence.length(); + for (first = 0; first < len && this.matches(sequence.charAt(first)); ++first) { + } + for (last = len - 1; last > first && this.matches(sequence.charAt(last)); --last) { + } + return first == 0 && last == len - 1 ? this.collapseFrom(sequence, replacement) : this.finishCollapseFrom(sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false); + } + + private String finishCollapseFrom(CharSequence sequence, int start, int end, char replacement, StringBuilder builder, boolean inMatchingGroup) { + for (int i = start; i < end; ++i) { + char c = sequence.charAt(i); + if (this.matches(c)) { + if (inMatchingGroup) continue; + builder.append(replacement); + inMatchingGroup = true; + continue; + } + builder.append(c); + inMatchingGroup = false; + } + return builder.toString(); + } + + @Override + @Deprecated + public boolean apply(Character character) { + return this.matches(character.charValue()); + } + + public String toString() { + return this.description; + } + + static { + StringBuilder builder = new StringBuilder(ZEROES.length()); + for (int i = 0; i < ZEROES.length(); ++i) { + builder.append((char)(ZEROES.charAt(i) + 9)); + } + NINES = builder.toString(); + DIGIT = new RangesMatcher("CharMatcher.DIGIT", ZEROES.toCharArray(), NINES.toCharArray()); + JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT"){ + + @Override + public boolean matches(char c) { + return Character.isDigit(c); + } + }; + JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER"){ + + @Override + public boolean matches(char c) { + return Character.isLetter(c); + } + }; + JAVA_LETTER_OR_DIGIT = new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT"){ + + @Override + public boolean matches(char c) { + return Character.isLetterOrDigit(c); + } + }; + JAVA_UPPER_CASE = new CharMatcher("CharMatcher.JAVA_UPPER_CASE"){ + + @Override + public boolean matches(char c) { + return Character.isUpperCase(c); + } + }; + JAVA_LOWER_CASE = new CharMatcher("CharMatcher.JAVA_LOWER_CASE"){ + + @Override + public boolean matches(char c) { + return Character.isLowerCase(c); + } + }; + JAVA_ISO_CONTROL = CharMatcher.inRange('\u0000', '\u001f').or(CharMatcher.inRange('\u007f', '\u009f')).withToString("CharMatcher.JAVA_ISO_CONTROL"); + INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u1680\u180e\u2000\u2028\u205f\u2066\u2067\u2068\u2069\u206a\u3000\ud800\ufeff\ufff9\ufffa".toCharArray(), " \u00a0\u00ad\u0604\u061c\u06dd\u070f\u1680\u180e\u200f\u202f\u2064\u2066\u2067\u2068\u2069\u206f\u3000\uf8ff\ufeff\ufff9\ufffb".toCharArray()); + SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH", "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(), "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray()); + ANY = new FastMatcher("CharMatcher.ANY"){ + + @Override + public boolean matches(char c) { + return true; + } + + @Override + public int indexIn(CharSequence sequence) { + return sequence.length() == 0 ? -1 : 0; + } + + @Override + public int indexIn(CharSequence sequence, int start) { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + return start == length ? -1 : start; + } + + @Override + public int lastIndexIn(CharSequence sequence) { + return sequence.length() - 1; + } + + @Override + public boolean matchesAllOf(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return true; + } + + @Override + public boolean matchesNoneOf(CharSequence sequence) { + return sequence.length() == 0; + } + + @Override + public String removeFrom(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return ""; + } + + @Override + public String replaceFrom(CharSequence sequence, char replacement) { + char[] array = new char[sequence.length()]; + Arrays.fill(array, replacement); + return new String(array); + } + + @Override + public String replaceFrom(CharSequence sequence, CharSequence replacement) { + StringBuilder retval = new StringBuilder(sequence.length() * replacement.length()); + for (int i = 0; i < sequence.length(); ++i) { + retval.append(replacement); + } + return retval.toString(); + } + + @Override + public String collapseFrom(CharSequence sequence, char replacement) { + return sequence.length() == 0 ? "" : String.valueOf(replacement); + } + + @Override + public String trimFrom(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return ""; + } + + @Override + public int countIn(CharSequence sequence) { + return sequence.length(); + } + + @Override + public CharMatcher and(CharMatcher other) { + return Preconditions.checkNotNull(other); + } + + @Override + public CharMatcher or(CharMatcher other) { + Preconditions.checkNotNull(other); + return this; + } + + @Override + public CharMatcher negate() { + return NONE; + } + }; + NONE = new FastMatcher("CharMatcher.NONE"){ + + @Override + public boolean matches(char c) { + return false; + } + + @Override + public int indexIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return -1; + } + + @Override + public int indexIn(CharSequence sequence, int start) { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + return -1; + } + + @Override + public int lastIndexIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return -1; + } + + @Override + public boolean matchesAllOf(CharSequence sequence) { + return sequence.length() == 0; + } + + @Override + public boolean matchesNoneOf(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return true; + } + + @Override + public String removeFrom(CharSequence sequence) { + return sequence.toString(); + } + + @Override + public String replaceFrom(CharSequence sequence, char replacement) { + return sequence.toString(); + } + + @Override + public String replaceFrom(CharSequence sequence, CharSequence replacement) { + Preconditions.checkNotNull(replacement); + return sequence.toString(); + } + + @Override + public String collapseFrom(CharSequence sequence, char replacement) { + return sequence.toString(); + } + + @Override + public String trimFrom(CharSequence sequence) { + return sequence.toString(); + } + + @Override + public String trimLeadingFrom(CharSequence sequence) { + return sequence.toString(); + } + + @Override + public String trimTrailingFrom(CharSequence sequence) { + return sequence.toString(); + } + + @Override + public int countIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return 0; + } + + @Override + public CharMatcher and(CharMatcher other) { + Preconditions.checkNotNull(other); + return this; + } + + @Override + public CharMatcher or(CharMatcher other) { + return Preconditions.checkNotNull(other); + } + + @Override + public CharMatcher negate() { + return ANY; + } + }; + WHITESPACE_SHIFT = Integer.numberOfLeadingZeros(WHITESPACE_TABLE.length() - 1); + WHITESPACE = new FastMatcher("WHITESPACE"){ + + @Override + public boolean matches(char c) { + return CharMatcher.WHITESPACE_TABLE.charAt(1682554634 * c >>> WHITESPACE_SHIFT) == c; + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + for (int i = 0; i < CharMatcher.WHITESPACE_TABLE.length(); ++i) { + table.set(CharMatcher.WHITESPACE_TABLE.charAt(i)); + } + } + }; + } + + @GwtIncompatible(value="java.util.BitSet") + private static class BitSetMatcher + extends FastMatcher { + private final BitSet table; + + private BitSetMatcher(BitSet table, String description) { + super(description); + if (table.length() + 64 < table.size()) { + table = (BitSet)table.clone(); + } + this.table = table; + } + + @Override + public boolean matches(char c) { + return this.table.get(c); + } + + @Override + void setBits(BitSet bitSet) { + bitSet.or(this.table); + } + } + + static final class NegatedFastMatcher + extends NegatedMatcher { + NegatedFastMatcher(CharMatcher original) { + super(original); + } + + NegatedFastMatcher(String toString, CharMatcher original) { + super(toString, original); + } + + @Override + public final CharMatcher precomputed() { + return this; + } + + @Override + CharMatcher withToString(String description) { + return new NegatedFastMatcher(description, this.original); + } + } + + static abstract class FastMatcher + extends CharMatcher { + FastMatcher() { + } + + FastMatcher(String description) { + super(description); + } + + @Override + public final CharMatcher precomputed() { + return this; + } + + @Override + public CharMatcher negate() { + return new NegatedFastMatcher(this); + } + } + + private static class Or + extends CharMatcher { + final CharMatcher first; + final CharMatcher second; + + Or(CharMatcher a, CharMatcher b, String description) { + super(description); + this.first = Preconditions.checkNotNull(a); + this.second = Preconditions.checkNotNull(b); + } + + Or(CharMatcher a, CharMatcher b) { + String string = String.valueOf(String.valueOf(a)); + String string2 = String.valueOf(String.valueOf(b)); + this(a, b, new StringBuilder(18 + string.length() + string2.length()).append("CharMatcher.or(").append(string).append(", ").append(string2).append(")").toString()); + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + this.first.setBits(table); + this.second.setBits(table); + } + + @Override + public boolean matches(char c) { + return this.first.matches(c) || this.second.matches(c); + } + + @Override + CharMatcher withToString(String description) { + return new Or(this.first, this.second, description); + } + } + + private static class And + extends CharMatcher { + final CharMatcher first; + final CharMatcher second; + + And(CharMatcher a, CharMatcher b) { + String string = String.valueOf(String.valueOf(a)); + String string2 = String.valueOf(String.valueOf(b)); + this(a, b, new StringBuilder(19 + string.length() + string2.length()).append("CharMatcher.and(").append(string).append(", ").append(string2).append(")").toString()); + } + + And(CharMatcher a, CharMatcher b, String description) { + super(description); + this.first = Preconditions.checkNotNull(a); + this.second = Preconditions.checkNotNull(b); + } + + @Override + public boolean matches(char c) { + return this.first.matches(c) && this.second.matches(c); + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + BitSet tmp1 = new BitSet(); + this.first.setBits(tmp1); + BitSet tmp2 = new BitSet(); + this.second.setBits(tmp2); + tmp1.and(tmp2); + table.or(tmp1); + } + + @Override + CharMatcher withToString(String description) { + return new And(this.first, this.second, description); + } + } + + private static class NegatedMatcher + extends CharMatcher { + final CharMatcher original; + + NegatedMatcher(String toString, CharMatcher original) { + super(toString); + this.original = original; + } + + NegatedMatcher(CharMatcher original) { + String string = String.valueOf(String.valueOf(original)); + this(new StringBuilder(9 + string.length()).append(string).append(".negate()").toString(), original); + } + + @Override + public boolean matches(char c) { + return !this.original.matches(c); + } + + @Override + public boolean matchesAllOf(CharSequence sequence) { + return this.original.matchesNoneOf(sequence); + } + + @Override + public boolean matchesNoneOf(CharSequence sequence) { + return this.original.matchesAllOf(sequence); + } + + @Override + public int countIn(CharSequence sequence) { + return sequence.length() - this.original.countIn(sequence); + } + + @Override + @GwtIncompatible(value="java.util.BitSet") + void setBits(BitSet table) { + BitSet tmp = new BitSet(); + this.original.setBits(tmp); + tmp.flip(0, 65536); + table.or(tmp); + } + + @Override + public CharMatcher negate() { + return this.original; + } + + @Override + CharMatcher withToString(String description) { + return new NegatedMatcher(description, this.original); + } + } + + private static class RangesMatcher + extends CharMatcher { + private final char[] rangeStarts; + private final char[] rangeEnds; + + RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) { + super(description); + this.rangeStarts = rangeStarts; + this.rangeEnds = rangeEnds; + Preconditions.checkArgument(rangeStarts.length == rangeEnds.length); + for (int i = 0; i < rangeStarts.length; ++i) { + Preconditions.checkArgument(rangeStarts[i] <= rangeEnds[i]); + if (i + 1 >= rangeStarts.length) continue; + Preconditions.checkArgument(rangeEnds[i] < rangeStarts[i + 1]); + } + } + + @Override + public boolean matches(char c) { + int index = Arrays.binarySearch(this.rangeStarts, c); + if (index >= 0) { + return true; + } + return (index = ~index - 1) >= 0 && c <= this.rangeEnds[index]; + } + } +} diff --git a/src/com/google/common/base/Charsets.java b/src/com/google/common/base/Charsets.java new file mode 100644 index 0000000..00cb6da --- /dev/null +++ b/src/com/google/common/base/Charsets.java @@ -0,0 +1,26 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.nio.charset.Charset; + +@GwtCompatible(emulated=true) +public final class Charsets { + @GwtIncompatible(value="Non-UTF-8 Charset") + public static final Charset US_ASCII = Charset.forName("US-ASCII"); + @GwtIncompatible(value="Non-UTF-8 Charset") + public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + public static final Charset UTF_8 = Charset.forName("UTF-8"); + @GwtIncompatible(value="Non-UTF-8 Charset") + public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); + @GwtIncompatible(value="Non-UTF-8 Charset") + public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); + @GwtIncompatible(value="Non-UTF-8 Charset") + public static final Charset UTF_16 = Charset.forName("UTF-16"); + + private Charsets() { + } +} diff --git a/src/com/google/common/base/Converter.java b/src/com/google/common/base/Converter.java new file mode 100644 index 0000000..36468eb --- /dev/null +++ b/src/com/google/common/base/Converter.java @@ -0,0 +1,305 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public abstract class Converter +implements Function { + private final boolean handleNullAutomatically; + private transient Converter reverse; + + protected Converter() { + this(true); + } + + Converter(boolean handleNullAutomatically) { + this.handleNullAutomatically = handleNullAutomatically; + } + + protected abstract B doForward(A var1); + + protected abstract A doBackward(B var1); + + @Nullable + public final B convert(@Nullable A a) { + return this.correctedDoForward(a); + } + + @Nullable + B correctedDoForward(@Nullable A a) { + if (this.handleNullAutomatically) { + return a == null ? null : (B)Preconditions.checkNotNull(this.doForward(a)); + } + return this.doForward(a); + } + + @Nullable + A correctedDoBackward(@Nullable B b) { + if (this.handleNullAutomatically) { + return b == null ? null : (A)Preconditions.checkNotNull(this.doBackward(b)); + } + return this.doBackward(b); + } + + public Iterable convertAll(final Iterable fromIterable) { + Preconditions.checkNotNull(fromIterable, "fromIterable"); + return new Iterable(){ + + @Override + public Iterator iterator() { + return new Iterator(){ + private final Iterator fromIterator; + { + this.fromIterator = fromIterable.iterator(); + } + + @Override + public boolean hasNext() { + return this.fromIterator.hasNext(); + } + + @Override + public B next() { + return Converter.this.convert(this.fromIterator.next()); + } + + @Override + public void remove() { + this.fromIterator.remove(); + } + }; + } + }; + } + + public Converter reverse() { + Converter result = this.reverse; + return result == null ? (this.reverse = new ReverseConverter(this)) : result; + } + + public final Converter andThen(Converter secondConverter) { + return this.doAndThen(secondConverter); + } + + Converter doAndThen(Converter secondConverter) { + return new ConverterComposition(this, Preconditions.checkNotNull(secondConverter)); + } + + @Override + @Deprecated + @Nullable + public final B apply(@Nullable A a) { + return this.convert(a); + } + + @Override + public boolean equals(@Nullable Object object) { + return super.equals(object); + } + + public static Converter from(Function forwardFunction, Function backwardFunction) { + return new FunctionBasedConverter(forwardFunction, backwardFunction); + } + + public static Converter identity() { + return IdentityConverter.INSTANCE; + } + + private static final class IdentityConverter + extends Converter + implements Serializable { + static final IdentityConverter INSTANCE = new IdentityConverter(); + private static final long serialVersionUID = 0L; + + private IdentityConverter() { + } + + @Override + protected T doForward(T t) { + return t; + } + + @Override + protected T doBackward(T t) { + return t; + } + + public IdentityConverter reverse() { + return this; + } + + @Override + Converter doAndThen(Converter otherConverter) { + return Preconditions.checkNotNull(otherConverter, "otherConverter"); + } + + public String toString() { + return "Converter.identity()"; + } + + private Object readResolve() { + return INSTANCE; + } + } + + private static final class FunctionBasedConverter + extends Converter + implements Serializable { + private final Function forwardFunction; + private final Function backwardFunction; + + private FunctionBasedConverter(Function forwardFunction, Function backwardFunction) { + this.forwardFunction = Preconditions.checkNotNull(forwardFunction); + this.backwardFunction = Preconditions.checkNotNull(backwardFunction); + } + + @Override + protected B doForward(A a) { + return this.forwardFunction.apply(a); + } + + @Override + protected A doBackward(B b) { + return this.backwardFunction.apply(b); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof FunctionBasedConverter) { + FunctionBasedConverter that = (FunctionBasedConverter)object; + return this.forwardFunction.equals(that.forwardFunction) && this.backwardFunction.equals(that.backwardFunction); + } + return false; + } + + public int hashCode() { + return this.forwardFunction.hashCode() * 31 + this.backwardFunction.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.forwardFunction)); + String string2 = String.valueOf(String.valueOf(this.backwardFunction)); + return new StringBuilder(18 + string.length() + string2.length()).append("Converter.from(").append(string).append(", ").append(string2).append(")").toString(); + } + } + + private static final class ConverterComposition + extends Converter + implements Serializable { + final Converter first; + final Converter second; + private static final long serialVersionUID = 0L; + + ConverterComposition(Converter first, Converter second) { + this.first = first; + this.second = second; + } + + @Override + protected C doForward(A a) { + throw new AssertionError(); + } + + @Override + protected A doBackward(C c) { + throw new AssertionError(); + } + + @Override + @Nullable + C correctedDoForward(@Nullable A a) { + return this.second.correctedDoForward(this.first.correctedDoForward(a)); + } + + @Override + @Nullable + A correctedDoBackward(@Nullable C c) { + return this.first.correctedDoBackward(this.second.correctedDoBackward(c)); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof ConverterComposition) { + ConverterComposition that = (ConverterComposition)object; + return this.first.equals(that.first) && this.second.equals(that.second); + } + return false; + } + + public int hashCode() { + return 31 * this.first.hashCode() + this.second.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.first)); + String string2 = String.valueOf(String.valueOf(this.second)); + return new StringBuilder(10 + string.length() + string2.length()).append(string).append(".andThen(").append(string2).append(")").toString(); + } + } + + private static final class ReverseConverter + extends Converter + implements Serializable { + final Converter original; + private static final long serialVersionUID = 0L; + + ReverseConverter(Converter original) { + this.original = original; + } + + @Override + protected A doForward(B b) { + throw new AssertionError(); + } + + @Override + protected B doBackward(A a) { + throw new AssertionError(); + } + + @Override + @Nullable + A correctedDoForward(@Nullable B b) { + return this.original.correctedDoBackward(b); + } + + @Override + @Nullable + B correctedDoBackward(@Nullable A a) { + return this.original.correctedDoForward(a); + } + + @Override + public Converter reverse() { + return this.original; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof ReverseConverter) { + ReverseConverter that = (ReverseConverter)object; + return this.original.equals(that.original); + } + return false; + } + + public int hashCode() { + return ~this.original.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.original)); + return new StringBuilder(10 + string.length()).append(string).append(".reverse()").toString(); + } + } +} diff --git a/src/com/google/common/base/Defaults.java b/src/com/google/common/base/Defaults.java new file mode 100644 index 0000000..6f2862d --- /dev/null +++ b/src/com/google/common/base/Defaults.java @@ -0,0 +1,40 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +public final class Defaults { + private static final Map, Object> DEFAULTS; + + private Defaults() { + } + + private static void put(Map, Object> map, Class type, T value) { + map.put(type, value); + } + + @Nullable + public static T defaultValue(Class type) { + Object t = DEFAULTS.get(Preconditions.checkNotNull(type)); + return (T)t; + } + + static { + HashMap map = new HashMap(); + Defaults.put(map, Boolean.TYPE, false); + Defaults.put(map, Character.TYPE, Character.valueOf('\u0000')); + Defaults.put(map, Byte.TYPE, (byte)0); + Defaults.put(map, Short.TYPE, (short)0); + Defaults.put(map, Integer.TYPE, 0); + Defaults.put(map, Long.TYPE, 0L); + Defaults.put(map, Float.TYPE, Float.valueOf(0.0f)); + Defaults.put(map, Double.TYPE, 0.0); + DEFAULTS = Collections.unmodifiableMap(map); + } +} diff --git a/src/com/google/common/base/Enums.java b/src/com/google/common/base/Enums.java new file mode 100644 index 0000000..d482b99 --- /dev/null +++ b/src/com/google/common/base/Enums.java @@ -0,0 +1,115 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Optional; +import com.google.common.base.Platform; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +@Beta +public final class Enums { + @GwtIncompatible(value="java.lang.ref.WeakReference") + private static final Map>, Map>>> enumConstantCache = new WeakHashMap(); + + private Enums() { + } + + @GwtIncompatible(value="reflection") + public static Field getField(Enum enumValue) { + Class clazz = enumValue.getDeclaringClass(); + try { + return clazz.getDeclaredField(enumValue.name()); + } + catch (NoSuchFieldException impossible) { + throw new AssertionError((Object)impossible); + } + } + + public static > Optional getIfPresent(Class enumClass, String value) { + Preconditions.checkNotNull(enumClass); + Preconditions.checkNotNull(value); + return Platform.getEnumIfPresent(enumClass, value); + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + private static > Map>> populateCache(Class enumClass) { + HashMap result = new HashMap(); + for (Enum enumInstance : EnumSet.allOf(enumClass)) { + result.put(enumInstance.name(), new WeakReference(enumInstance)); + } + enumConstantCache.put(enumClass, result); + return result; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @GwtIncompatible(value="java.lang.ref.WeakReference") + static > Map>> getEnumConstants(Class enumClass) { + Map>, Map>>> map = enumConstantCache; + synchronized (map) { + Map> constants = enumConstantCache.get(enumClass); + if (constants == null) { + constants = Enums.populateCache(enumClass); + } + return constants; + } + } + + public static > Converter stringConverter(Class enumClass) { + return new StringConverter(enumClass); + } + + private static final class StringConverter> + extends Converter + implements Serializable { + private final Class enumClass; + private static final long serialVersionUID = 0L; + + StringConverter(Class enumClass) { + this.enumClass = Preconditions.checkNotNull(enumClass); + } + + @Override + protected T doForward(String value) { + return Enum.valueOf(this.enumClass, value); + } + + @Override + protected String doBackward(T enumValue) { + return ((Enum)enumValue).name(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof StringConverter) { + StringConverter that = (StringConverter)object; + return this.enumClass.equals(that.enumClass); + } + return false; + } + + public int hashCode() { + return this.enumClass.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.enumClass.getName())); + return new StringBuilder(29 + string.length()).append("Enums.stringConverter(").append(string).append(".class)").toString(); + } + } +} diff --git a/src/com/google/common/base/Equivalence.java b/src/com/google/common/base/Equivalence.java new file mode 100644 index 0000000..2fcaced --- /dev/null +++ b/src/com/google/common/base/Equivalence.java @@ -0,0 +1,199 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.FunctionalEquivalence; +import com.google.common.base.Objects; +import com.google.common.base.PairwiseEquivalence; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class Equivalence { + protected Equivalence() { + } + + public final boolean equivalent(@Nullable T a, @Nullable T b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return this.doEquivalent(a, b); + } + + protected abstract boolean doEquivalent(T var1, T var2); + + public final int hash(@Nullable T t) { + if (t == null) { + return 0; + } + return this.doHash(t); + } + + protected abstract int doHash(T var1); + + public final Equivalence onResultOf(Function function) { + return new FunctionalEquivalence(function, this); + } + + public final Wrapper wrap(@Nullable S reference) { + return new Wrapper(this, reference); + } + + @GwtCompatible(serializable=true) + public final Equivalence> pairwise() { + return new PairwiseEquivalence(this); + } + + @Beta + public final Predicate equivalentTo(@Nullable T target) { + return new EquivalentToPredicate(this, target); + } + + public static Equivalence equals() { + return Equals.INSTANCE; + } + + public static Equivalence identity() { + return Identity.INSTANCE; + } + + static final class Identity + extends Equivalence + implements Serializable { + static final Identity INSTANCE = new Identity(); + private static final long serialVersionUID = 1L; + + Identity() { + } + + @Override + protected boolean doEquivalent(Object a, Object b) { + return false; + } + + @Override + protected int doHash(Object o) { + return System.identityHashCode(o); + } + + private Object readResolve() { + return INSTANCE; + } + } + + static final class Equals + extends Equivalence + implements Serializable { + static final Equals INSTANCE = new Equals(); + private static final long serialVersionUID = 1L; + + Equals() { + } + + @Override + protected boolean doEquivalent(Object a, Object b) { + return a.equals(b); + } + + @Override + protected int doHash(Object o) { + return o.hashCode(); + } + + private Object readResolve() { + return INSTANCE; + } + } + + private static final class EquivalentToPredicate + implements Predicate, + Serializable { + private final Equivalence equivalence; + @Nullable + private final T target; + private static final long serialVersionUID = 0L; + + EquivalentToPredicate(Equivalence equivalence, @Nullable T target) { + this.equivalence = Preconditions.checkNotNull(equivalence); + this.target = target; + } + + @Override + public boolean apply(@Nullable T input) { + return this.equivalence.equivalent(input, this.target); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof EquivalentToPredicate) { + EquivalentToPredicate that = (EquivalentToPredicate)obj; + return this.equivalence.equals(that.equivalence) && Objects.equal(this.target, that.target); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.equivalence, this.target); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.equivalence)); + String string2 = String.valueOf(String.valueOf(this.target)); + return new StringBuilder(15 + string.length() + string2.length()).append(string).append(".equivalentTo(").append(string2).append(")").toString(); + } + } + + public static final class Wrapper + implements Serializable { + private final Equivalence equivalence; + @Nullable + private final T reference; + private static final long serialVersionUID = 0L; + + private Wrapper(Equivalence equivalence, @Nullable T reference) { + this.equivalence = Preconditions.checkNotNull(equivalence); + this.reference = reference; + } + + @Nullable + public T get() { + return this.reference; + } + + public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Wrapper) { + Wrapper that = (Wrapper)obj; + if (this.equivalence.equals(that.equivalence)) { + Equivalence equivalence = this.equivalence; + return equivalence.equivalent(this.reference, that.reference); + } + } + return false; + } + + public int hashCode() { + return this.equivalence.hash(this.reference); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.equivalence)); + String string2 = String.valueOf(String.valueOf(this.reference)); + return new StringBuilder(7 + string.length() + string2.length()).append(string).append(".wrap(").append(string2).append(")").toString(); + } + } +} diff --git a/src/com/google/common/base/FinalizablePhantomReference.java b/src/com/google/common/base/FinalizablePhantomReference.java new file mode 100644 index 0000000..d7db526 --- /dev/null +++ b/src/com/google/common/base/FinalizablePhantomReference.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.base.FinalizableReference; +import com.google.common.base.FinalizableReferenceQueue; +import java.lang.ref.PhantomReference; + +public abstract class FinalizablePhantomReference +extends PhantomReference +implements FinalizableReference { + protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) { + super(referent, queue.queue); + queue.cleanUp(); + } +} diff --git a/src/com/google/common/base/FinalizableReference.java b/src/com/google/common/base/FinalizableReference.java new file mode 100644 index 0000000..a0afedb --- /dev/null +++ b/src/com/google/common/base/FinalizableReference.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +public interface FinalizableReference { + public void finalizeReferent(); +} diff --git a/src/com/google/common/base/FinalizableReferenceQueue.java b/src/com/google/common/base/FinalizableReferenceQueue.java new file mode 100644 index 0000000..2102cd3 --- /dev/null +++ b/src/com/google/common/base/FinalizableReferenceQueue.java @@ -0,0 +1,182 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.FinalizableReference; +import java.io.Closeable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +public class FinalizableReferenceQueue +implements Closeable { + private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName()); + private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer"; + private static final Method startFinalizer; + final ReferenceQueue queue = new ReferenceQueue(); + final PhantomReference frqRef = new PhantomReference(this, this.queue); + final boolean threadStarted; + + public FinalizableReferenceQueue() { + boolean threadStarted = false; + try { + startFinalizer.invoke(null, FinalizableReference.class, this.queue, this.frqRef); + threadStarted = true; + } + catch (IllegalAccessException impossible) { + throw new AssertionError((Object)impossible); + } + catch (Throwable t) { + logger.log(Level.INFO, "Failed to start reference finalizer thread. Reference cleanup will only occur when new references are created.", t); + } + this.threadStarted = threadStarted; + } + + @Override + public void close() { + this.frqRef.enqueue(); + this.cleanUp(); + } + + void cleanUp() { + Reference reference; + if (this.threadStarted) { + return; + } + while ((reference = this.queue.poll()) != null) { + reference.clear(); + try { + ((FinalizableReference)((Object)reference)).finalizeReferent(); + } + catch (Throwable t) { + logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + } + } + } + + private static Class loadFinalizer(FinalizerLoader ... loaders) { + for (FinalizerLoader loader : loaders) { + Class finalizer = loader.loadFinalizer(); + if (finalizer == null) continue; + return finalizer; + } + throw new AssertionError(); + } + + static Method getStartFinalizer(Class finalizer) { + try { + return finalizer.getMethod("startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class); + } + catch (NoSuchMethodException e) { + throw new AssertionError((Object)e); + } + } + + static { + Class finalizer = FinalizableReferenceQueue.loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader()); + startFinalizer = FinalizableReferenceQueue.getStartFinalizer(finalizer); + } + + static class DirectLoader + implements FinalizerLoader { + DirectLoader() { + } + + @Override + public Class loadFinalizer() { + try { + return Class.forName(FinalizableReferenceQueue.FINALIZER_CLASS_NAME); + } + catch (ClassNotFoundException e) { + throw new AssertionError((Object)e); + } + } + } + + static class DecoupledLoader + implements FinalizerLoader { + private static final String LOADING_ERROR = "Could not load Finalizer in its own class loader.Loading Finalizer in the current class loader instead. As a result, you will not be ableto garbage collect this class loader. To support reclaiming this class loader, eitherresolve the underlying issue, or move Google Collections to your system class path."; + + DecoupledLoader() { + } + + @Override + public Class loadFinalizer() { + try { + URLClassLoader finalizerLoader = this.newLoader(this.getBaseUrl()); + return finalizerLoader.loadClass(FinalizableReferenceQueue.FINALIZER_CLASS_NAME); + } + catch (Exception e) { + logger.log(Level.WARNING, LOADING_ERROR, e); + return null; + } + } + + URL getBaseUrl() throws IOException { + String finalizerPath = String.valueOf(FinalizableReferenceQueue.FINALIZER_CLASS_NAME.replace('.', '/')).concat(".class"); + URL finalizerUrl = this.getClass().getClassLoader().getResource(finalizerPath); + if (finalizerUrl == null) { + throw new FileNotFoundException(finalizerPath); + } + String urlString = finalizerUrl.toString(); + if (!urlString.endsWith(finalizerPath)) { + String string = String.valueOf(urlString); + throw new IOException(string.length() != 0 ? "Unsupported path style: ".concat(string) : new String("Unsupported path style: ")); + } + urlString = urlString.substring(0, urlString.length() - finalizerPath.length()); + return new URL(finalizerUrl, urlString); + } + + URLClassLoader newLoader(URL base) { + return new URLClassLoader(new URL[]{base}, null); + } + } + + static class SystemLoader + implements FinalizerLoader { + @VisibleForTesting + static boolean disabled; + + SystemLoader() { + } + + @Override + public Class loadFinalizer() { + ClassLoader systemLoader; + if (disabled) { + return null; + } + try { + systemLoader = ClassLoader.getSystemClassLoader(); + } + catch (SecurityException e) { + logger.info("Not allowed to access system class loader."); + return null; + } + if (systemLoader != null) { + try { + return systemLoader.loadClass(FinalizableReferenceQueue.FINALIZER_CLASS_NAME); + } + catch (ClassNotFoundException e) { + return null; + } + } + return null; + } + } + + static interface FinalizerLoader { + @Nullable + public Class loadFinalizer(); + } +} diff --git a/src/com/google/common/base/FinalizableSoftReference.java b/src/com/google/common/base/FinalizableSoftReference.java new file mode 100644 index 0000000..61838e0 --- /dev/null +++ b/src/com/google/common/base/FinalizableSoftReference.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.base.FinalizableReference; +import com.google.common.base.FinalizableReferenceQueue; +import java.lang.ref.SoftReference; + +public abstract class FinalizableSoftReference +extends SoftReference +implements FinalizableReference { + protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) { + super(referent, queue.queue); + queue.cleanUp(); + } +} diff --git a/src/com/google/common/base/FinalizableWeakReference.java b/src/com/google/common/base/FinalizableWeakReference.java new file mode 100644 index 0000000..3b3f0f0 --- /dev/null +++ b/src/com/google/common/base/FinalizableWeakReference.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.base.FinalizableReference; +import com.google.common.base.FinalizableReferenceQueue; +import java.lang.ref.WeakReference; + +public abstract class FinalizableWeakReference +extends WeakReference +implements FinalizableReference { + protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) { + super(referent, queue.queue); + queue.cleanUp(); + } +} diff --git a/src/com/google/common/base/Function.java b/src/com/google/common/base/Function.java new file mode 100644 index 0000000..77bebd1 --- /dev/null +++ b/src/com/google/common/base/Function.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public interface Function { + @Nullable + public T apply(@Nullable F var1); + + public boolean equals(@Nullable Object var1); +} diff --git a/src/com/google/common/base/FunctionalEquivalence.java b/src/com/google/common/base/FunctionalEquivalence.java new file mode 100644 index 0000000..853dd99 --- /dev/null +++ b/src/com/google/common/base/FunctionalEquivalence.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +final class FunctionalEquivalence +extends Equivalence +implements Serializable { + private static final long serialVersionUID = 0L; + private final Function function; + private final Equivalence resultEquivalence; + + FunctionalEquivalence(Function function, Equivalence resultEquivalence) { + this.function = Preconditions.checkNotNull(function); + this.resultEquivalence = Preconditions.checkNotNull(resultEquivalence); + } + + @Override + protected boolean doEquivalent(F a, F b) { + return this.resultEquivalence.equivalent(this.function.apply(a), this.function.apply(b)); + } + + @Override + protected int doHash(F a) { + return this.resultEquivalence.hash(this.function.apply(a)); + } + + public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof FunctionalEquivalence) { + FunctionalEquivalence that = (FunctionalEquivalence)obj; + return this.function.equals(that.function) && this.resultEquivalence.equals(that.resultEquivalence); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.function, this.resultEquivalence); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.resultEquivalence)); + String string2 = String.valueOf(String.valueOf(this.function)); + return new StringBuilder(13 + string.length() + string2.length()).append(string).append(".onResultOf(").append(string2).append(")").toString(); + } +} diff --git a/src/com/google/common/base/Functions.java b/src/com/google/common/base/Functions.java new file mode 100644 index 0000000..c3c4a7b --- /dev/null +++ b/src/com/google/common/base/Functions.java @@ -0,0 +1,299 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Functions { + private Functions() { + } + + public static Function toStringFunction() { + return ToStringFunction.INSTANCE; + } + + public static Function identity() { + return IdentityFunction.INSTANCE; + } + + public static Function forMap(Map map) { + return new FunctionForMapNoDefault(map); + } + + public static Function forMap(Map map, @Nullable V defaultValue) { + return new ForMapWithDefault(map, defaultValue); + } + + public static Function compose(Function g, Function f) { + return new FunctionComposition(g, f); + } + + public static Function forPredicate(Predicate predicate) { + return new PredicateFunction(predicate); + } + + public static Function constant(@Nullable E value) { + return new ConstantFunction(value); + } + + @Beta + public static Function forSupplier(Supplier supplier) { + return new SupplierFunction(supplier); + } + + private static class SupplierFunction + implements Function, + Serializable { + private final Supplier supplier; + private static final long serialVersionUID = 0L; + + private SupplierFunction(Supplier supplier) { + this.supplier = Preconditions.checkNotNull(supplier); + } + + @Override + public T apply(@Nullable Object input) { + return this.supplier.get(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof SupplierFunction) { + SupplierFunction that = (SupplierFunction)obj; + return this.supplier.equals(that.supplier); + } + return false; + } + + public int hashCode() { + return this.supplier.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.supplier)); + return new StringBuilder(13 + string.length()).append("forSupplier(").append(string).append(")").toString(); + } + } + + private static class ConstantFunction + implements Function, + Serializable { + private final E value; + private static final long serialVersionUID = 0L; + + public ConstantFunction(@Nullable E value) { + this.value = value; + } + + @Override + public E apply(@Nullable Object from) { + return this.value; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof ConstantFunction) { + ConstantFunction that = (ConstantFunction)obj; + return Objects.equal(this.value, that.value); + } + return false; + } + + public int hashCode() { + return this.value == null ? 0 : this.value.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.value)); + return new StringBuilder(10 + string.length()).append("constant(").append(string).append(")").toString(); + } + } + + private static class PredicateFunction + implements Function, + Serializable { + private final Predicate predicate; + private static final long serialVersionUID = 0L; + + private PredicateFunction(Predicate predicate) { + this.predicate = Preconditions.checkNotNull(predicate); + } + + @Override + public Boolean apply(@Nullable T t) { + return this.predicate.apply(t); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof PredicateFunction) { + PredicateFunction that = (PredicateFunction)obj; + return this.predicate.equals(that.predicate); + } + return false; + } + + public int hashCode() { + return this.predicate.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.predicate)); + return new StringBuilder(14 + string.length()).append("forPredicate(").append(string).append(")").toString(); + } + } + + private static class FunctionComposition + implements Function, + Serializable { + private final Function g; + private final Function f; + private static final long serialVersionUID = 0L; + + public FunctionComposition(Function g, Function f) { + this.g = Preconditions.checkNotNull(g); + this.f = Preconditions.checkNotNull(f); + } + + @Override + public C apply(@Nullable A a) { + return this.g.apply(this.f.apply(a)); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof FunctionComposition) { + FunctionComposition that = (FunctionComposition)obj; + return this.f.equals(that.f) && this.g.equals(that.g); + } + return false; + } + + public int hashCode() { + return this.f.hashCode() ^ this.g.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.g)); + String string2 = String.valueOf(String.valueOf(this.f)); + return new StringBuilder(2 + string.length() + string2.length()).append(string).append("(").append(string2).append(")").toString(); + } + } + + private static class ForMapWithDefault + implements Function, + Serializable { + final Map map; + final V defaultValue; + private static final long serialVersionUID = 0L; + + ForMapWithDefault(Map map, @Nullable V defaultValue) { + this.map = Preconditions.checkNotNull(map); + this.defaultValue = defaultValue; + } + + @Override + public V apply(@Nullable K key) { + V result = this.map.get(key); + return result != null || this.map.containsKey(key) ? result : this.defaultValue; + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof ForMapWithDefault) { + ForMapWithDefault that = (ForMapWithDefault)o; + return this.map.equals(that.map) && Objects.equal(this.defaultValue, that.defaultValue); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.map, this.defaultValue); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.map)); + String string2 = String.valueOf(String.valueOf(this.defaultValue)); + return new StringBuilder(23 + string.length() + string2.length()).append("forMap(").append(string).append(", defaultValue=").append(string2).append(")").toString(); + } + } + + private static class FunctionForMapNoDefault + implements Function, + Serializable { + final Map map; + private static final long serialVersionUID = 0L; + + FunctionForMapNoDefault(Map map) { + this.map = Preconditions.checkNotNull(map); + } + + @Override + public V apply(@Nullable K key) { + V result = this.map.get(key); + Preconditions.checkArgument(result != null || this.map.containsKey(key), "Key '%s' not present in map", key); + return result; + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof FunctionForMapNoDefault) { + FunctionForMapNoDefault that = (FunctionForMapNoDefault)o; + return this.map.equals(that.map); + } + return false; + } + + public int hashCode() { + return this.map.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.map)); + return new StringBuilder(8 + string.length()).append("forMap(").append(string).append(")").toString(); + } + } + + private static enum IdentityFunction implements Function + { + INSTANCE; + + + @Override + @Nullable + public Object apply(@Nullable Object o) { + return o; + } + + public String toString() { + return "identity"; + } + } + + private static enum ToStringFunction implements Function + { + INSTANCE; + + + @Override + public String apply(Object o) { + Preconditions.checkNotNull(o); + return o.toString(); + } + + public String toString() { + return "toString"; + } + } +} diff --git a/src/com/google/common/base/Joiner.java b/src/com/google/common/base/Joiner.java new file mode 100644 index 0000000..b3d2deb --- /dev/null +++ b/src/com/google/common/base/Joiner.java @@ -0,0 +1,267 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@GwtCompatible +public class Joiner { + private final String separator; + + public static Joiner on(String separator) { + return new Joiner(separator); + } + + public static Joiner on(char separator) { + return new Joiner(String.valueOf(separator)); + } + + private Joiner(String separator) { + this.separator = Preconditions.checkNotNull(separator); + } + + private Joiner(Joiner prototype) { + this.separator = prototype.separator; + } + + public A appendTo(A appendable, Iterable parts) throws IOException { + return this.appendTo(appendable, parts.iterator()); + } + + public A appendTo(A appendable, Iterator parts) throws IOException { + Preconditions.checkNotNull(appendable); + if (parts.hasNext()) { + appendable.append(this.toString(parts.next())); + while (parts.hasNext()) { + appendable.append(this.separator); + appendable.append(this.toString(parts.next())); + } + } + return appendable; + } + + public final A appendTo(A appendable, Object[] parts) throws IOException { + return this.appendTo(appendable, Arrays.asList(parts)); + } + + public final A appendTo(A appendable, @Nullable Object first, @Nullable Object second, Object ... rest) throws IOException { + return this.appendTo(appendable, Joiner.iterable(first, second, rest)); + } + + public final StringBuilder appendTo(StringBuilder builder, Iterable parts) { + return this.appendTo(builder, parts.iterator()); + } + + public final StringBuilder appendTo(StringBuilder builder, Iterator parts) { + try { + this.appendTo((Appendable)builder, parts); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + return builder; + } + + public final StringBuilder appendTo(StringBuilder builder, Object[] parts) { + return this.appendTo(builder, (Iterable)Arrays.asList(parts)); + } + + public final StringBuilder appendTo(StringBuilder builder, @Nullable Object first, @Nullable Object second, Object ... rest) { + return this.appendTo(builder, Joiner.iterable(first, second, rest)); + } + + public final String join(Iterable parts) { + return this.join(parts.iterator()); + } + + public final String join(Iterator parts) { + return this.appendTo(new StringBuilder(), parts).toString(); + } + + public final String join(Object[] parts) { + return this.join(Arrays.asList(parts)); + } + + public final String join(@Nullable Object first, @Nullable Object second, Object ... rest) { + return this.join(Joiner.iterable(first, second, rest)); + } + + @CheckReturnValue + public Joiner useForNull(final String nullText) { + Preconditions.checkNotNull(nullText); + return new Joiner(this){ + + @Override + CharSequence toString(@Nullable Object part) { + return part == null ? nullText : Joiner.this.toString(part); + } + + @Override + public Joiner useForNull(String nullText2) { + throw new UnsupportedOperationException("already specified useForNull"); + } + + @Override + public Joiner skipNulls() { + throw new UnsupportedOperationException("already specified useForNull"); + } + }; + } + + @CheckReturnValue + public Joiner skipNulls() { + return new Joiner(this){ + + @Override + public A appendTo(A appendable, Iterator parts) throws IOException { + Object part; + Preconditions.checkNotNull(appendable, "appendable"); + Preconditions.checkNotNull(parts, "parts"); + while (parts.hasNext()) { + part = parts.next(); + if (part == null) continue; + appendable.append(Joiner.this.toString(part)); + break; + } + while (parts.hasNext()) { + part = parts.next(); + if (part == null) continue; + appendable.append(Joiner.this.separator); + appendable.append(Joiner.this.toString(part)); + } + return appendable; + } + + @Override + public Joiner useForNull(String nullText) { + throw new UnsupportedOperationException("already specified skipNulls"); + } + + @Override + public MapJoiner withKeyValueSeparator(String kvs) { + throw new UnsupportedOperationException("can't use .skipNulls() with maps"); + } + }; + } + + @CheckReturnValue + public MapJoiner withKeyValueSeparator(String keyValueSeparator) { + return new MapJoiner(this, keyValueSeparator); + } + + CharSequence toString(Object part) { + Preconditions.checkNotNull(part); + return part instanceof CharSequence ? (CharSequence)part : part.toString(); + } + + private static Iterable iterable(final Object first, final Object second, final Object[] rest) { + Preconditions.checkNotNull(rest); + return new AbstractList(){ + + @Override + public int size() { + return rest.length + 2; + } + + @Override + public Object get(int index) { + switch (index) { + case 0: { + return first; + } + case 1: { + return second; + } + } + return rest[index - 2]; + } + }; + } + + public static final class MapJoiner { + private final Joiner joiner; + private final String keyValueSeparator; + + private MapJoiner(Joiner joiner, String keyValueSeparator) { + this.joiner = joiner; + this.keyValueSeparator = Preconditions.checkNotNull(keyValueSeparator); + } + + public A appendTo(A appendable, Map map) throws IOException { + return this.appendTo(appendable, map.entrySet()); + } + + public StringBuilder appendTo(StringBuilder builder, Map map) { + return this.appendTo(builder, (Iterable>)map.entrySet()); + } + + public String join(Map map) { + return this.join(map.entrySet()); + } + + @Beta + public A appendTo(A appendable, Iterable> entries) throws IOException { + return this.appendTo(appendable, entries.iterator()); + } + + @Beta + public A appendTo(A appendable, Iterator> parts) throws IOException { + Preconditions.checkNotNull(appendable); + if (parts.hasNext()) { + Map.Entry entry = parts.next(); + appendable.append(this.joiner.toString(entry.getKey())); + appendable.append(this.keyValueSeparator); + appendable.append(this.joiner.toString(entry.getValue())); + while (parts.hasNext()) { + appendable.append(this.joiner.separator); + Map.Entry e = parts.next(); + appendable.append(this.joiner.toString(e.getKey())); + appendable.append(this.keyValueSeparator); + appendable.append(this.joiner.toString(e.getValue())); + } + } + return appendable; + } + + @Beta + public StringBuilder appendTo(StringBuilder builder, Iterable> entries) { + return this.appendTo(builder, entries.iterator()); + } + + @Beta + public StringBuilder appendTo(StringBuilder builder, Iterator> entries) { + try { + this.appendTo((Appendable)builder, entries); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + return builder; + } + + @Beta + public String join(Iterable> entries) { + return this.join(entries.iterator()); + } + + @Beta + public String join(Iterator> entries) { + return this.appendTo(new StringBuilder(), entries).toString(); + } + + @CheckReturnValue + public MapJoiner useForNull(String nullText) { + return new MapJoiner(this.joiner.useForNull(nullText), this.keyValueSeparator); + } + } +} diff --git a/src/com/google/common/base/MoreObjects.java b/src/com/google/common/base/MoreObjects.java new file mode 100644 index 0000000..3408cbe --- /dev/null +++ b/src/com/google/common/base/MoreObjects.java @@ -0,0 +1,160 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + +@GwtCompatible +public final class MoreObjects { + public static T firstNonNull(@Nullable T first, @Nullable T second) { + return first != null ? first : Preconditions.checkNotNull(second); + } + + public static ToStringHelper toStringHelper(Object self) { + return new ToStringHelper(MoreObjects.simpleName(self.getClass())); + } + + public static ToStringHelper toStringHelper(Class clazz) { + return new ToStringHelper(MoreObjects.simpleName(clazz)); + } + + public static ToStringHelper toStringHelper(String className) { + return new ToStringHelper(className); + } + + static String simpleName(Class clazz) { + String name = clazz.getName(); + int start = (name = name.replaceAll("\\$[0-9]+", "\\$")).lastIndexOf(36); + if (start == -1) { + start = name.lastIndexOf(46); + } + return name.substring(start + 1); + } + + private MoreObjects() { + } + + public static final class ToStringHelper { + private final String className; + private ValueHolder holderHead; + private ValueHolder holderTail; + private boolean omitNullValues; + + private ToStringHelper(String className) { + this.holderTail = this.holderHead = new ValueHolder(); + this.omitNullValues = false; + this.className = Preconditions.checkNotNull(className); + } + + public ToStringHelper omitNullValues() { + this.omitNullValues = true; + return this; + } + + public ToStringHelper add(String name, @Nullable Object value) { + return this.addHolder(name, value); + } + + public ToStringHelper add(String name, boolean value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, char value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, double value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, float value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, int value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, long value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper addValue(@Nullable Object value) { + return this.addHolder(value); + } + + public ToStringHelper addValue(boolean value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(char value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(double value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(float value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(int value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(long value) { + return this.addHolder(String.valueOf(value)); + } + + public String toString() { + boolean omitNullValuesSnapshot = this.omitNullValues; + String nextSeparator = ""; + StringBuilder builder = new StringBuilder(32).append(this.className).append('{'); + ValueHolder valueHolder = this.holderHead.next; + while (valueHolder != null) { + if (!omitNullValuesSnapshot || valueHolder.value != null) { + builder.append(nextSeparator); + nextSeparator = ", "; + if (valueHolder.name != null) { + builder.append(valueHolder.name).append('='); + } + builder.append(valueHolder.value); + } + valueHolder = valueHolder.next; + } + return builder.append('}').toString(); + } + + private ValueHolder addHolder() { + ValueHolder valueHolder; + this.holderTail = this.holderTail.next = (valueHolder = new ValueHolder()); + return valueHolder; + } + + private ToStringHelper addHolder(@Nullable Object value) { + ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + return this; + } + + private ToStringHelper addHolder(String name, @Nullable Object value) { + ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + valueHolder.name = Preconditions.checkNotNull(name); + return this; + } + + private static final class ValueHolder { + String name; + Object value; + ValueHolder next; + + private ValueHolder() { + } + } + } +} diff --git a/src/com/google/common/base/Objects.java b/src/com/google/common/base/Objects.java new file mode 100644 index 0000000..62bfb7c --- /dev/null +++ b/src/com/google/common/base/Objects.java @@ -0,0 +1,168 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import java.util.Arrays; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Objects { + private Objects() { + } + + @CheckReturnValue + public static boolean equal(@Nullable Object a, @Nullable Object b) { + return a == b || a != null && a.equals(b); + } + + public static int hashCode(Object ... objects) { + return Arrays.hashCode(objects); + } + + @Deprecated + public static ToStringHelper toStringHelper(Object self) { + return new ToStringHelper(MoreObjects.simpleName(self.getClass())); + } + + @Deprecated + public static ToStringHelper toStringHelper(Class clazz) { + return new ToStringHelper(MoreObjects.simpleName(clazz)); + } + + @Deprecated + public static ToStringHelper toStringHelper(String className) { + return new ToStringHelper(className); + } + + @Deprecated + public static T firstNonNull(@Nullable T first, @Nullable T second) { + return MoreObjects.firstNonNull(first, second); + } + + @Deprecated + public static final class ToStringHelper { + private final String className; + private ValueHolder holderHead; + private ValueHolder holderTail; + private boolean omitNullValues; + + private ToStringHelper(String className) { + this.holderTail = this.holderHead = new ValueHolder(); + this.omitNullValues = false; + this.className = Preconditions.checkNotNull(className); + } + + public ToStringHelper omitNullValues() { + this.omitNullValues = true; + return this; + } + + public ToStringHelper add(String name, @Nullable Object value) { + return this.addHolder(name, value); + } + + public ToStringHelper add(String name, boolean value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, char value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, double value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, float value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, int value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper add(String name, long value) { + return this.addHolder(name, String.valueOf(value)); + } + + public ToStringHelper addValue(@Nullable Object value) { + return this.addHolder(value); + } + + public ToStringHelper addValue(boolean value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(char value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(double value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(float value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(int value) { + return this.addHolder(String.valueOf(value)); + } + + public ToStringHelper addValue(long value) { + return this.addHolder(String.valueOf(value)); + } + + public String toString() { + boolean omitNullValuesSnapshot = this.omitNullValues; + String nextSeparator = ""; + StringBuilder builder = new StringBuilder(32).append(this.className).append('{'); + ValueHolder valueHolder = this.holderHead.next; + while (valueHolder != null) { + if (!omitNullValuesSnapshot || valueHolder.value != null) { + builder.append(nextSeparator); + nextSeparator = ", "; + if (valueHolder.name != null) { + builder.append(valueHolder.name).append('='); + } + builder.append(valueHolder.value); + } + valueHolder = valueHolder.next; + } + return builder.append('}').toString(); + } + + private ValueHolder addHolder() { + ValueHolder valueHolder; + this.holderTail = this.holderTail.next = (valueHolder = new ValueHolder()); + return valueHolder; + } + + private ToStringHelper addHolder(@Nullable Object value) { + ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + return this; + } + + private ToStringHelper addHolder(String name, @Nullable Object value) { + ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + valueHolder.name = Preconditions.checkNotNull(name); + return this; + } + + private static final class ValueHolder { + String name; + Object value; + ValueHolder next; + + private ValueHolder() { + } + } + } +} diff --git a/src/com/google/common/base/Optional.java b/src/com/google/common/base/Optional.java new file mode 100644 index 0000000..e817827 --- /dev/null +++ b/src/com/google/common/base/Optional.java @@ -0,0 +1,89 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Absent; +import com.google.common.base.AbstractIterator; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Present; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +public abstract class Optional +implements Serializable { + private static final long serialVersionUID = 0L; + + public static Optional absent() { + return Absent.withType(); + } + + public static Optional of(T reference) { + return new Present(Preconditions.checkNotNull(reference)); + } + + public static Optional fromNullable(@Nullable T nullableReference) { + return nullableReference == null ? Optional.absent() : new Present(nullableReference); + } + + Optional() { + } + + public abstract boolean isPresent(); + + public abstract T get(); + + public abstract T or(T var1); + + public abstract Optional or(Optional var1); + + @Beta + public abstract T or(Supplier var1); + + @Nullable + public abstract T orNull(); + + public abstract Set asSet(); + + public abstract Optional transform(Function var1); + + public abstract boolean equals(@Nullable Object var1); + + public abstract int hashCode(); + + public abstract String toString(); + + @Beta + public static Iterable presentInstances(final Iterable> optionals) { + Preconditions.checkNotNull(optionals); + return new Iterable(){ + + @Override + public Iterator iterator() { + return new AbstractIterator(){ + private final Iterator> iterator; + { + this.iterator = Preconditions.checkNotNull(optionals.iterator()); + } + + @Override + protected T computeNext() { + while (this.iterator.hasNext()) { + Optional optional = this.iterator.next(); + if (!optional.isPresent()) continue; + return optional.get(); + } + return this.endOfData(); + } + }; + } + }; + } +} diff --git a/src/com/google/common/base/PairwiseEquivalence.java b/src/com/google/common/base/PairwiseEquivalence.java new file mode 100644 index 0000000..07201d5 --- /dev/null +++ b/src/com/google/common/base/PairwiseEquivalence.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class PairwiseEquivalence +extends Equivalence> +implements Serializable { + final Equivalence elementEquivalence; + private static final long serialVersionUID = 1L; + + PairwiseEquivalence(Equivalence elementEquivalence) { + this.elementEquivalence = Preconditions.checkNotNull(elementEquivalence); + } + + @Override + protected boolean doEquivalent(Iterable iterableA, Iterable iterableB) { + Iterator iteratorA = iterableA.iterator(); + Iterator iteratorB = iterableB.iterator(); + while (iteratorA.hasNext() && iteratorB.hasNext()) { + if (this.elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) continue; + return false; + } + return !iteratorA.hasNext() && !iteratorB.hasNext(); + } + + @Override + protected int doHash(Iterable iterable) { + int hash = 78721; + for (T element : iterable) { + hash = hash * 24943 + this.elementEquivalence.hash(element); + } + return hash; + } + + public boolean equals(@Nullable Object object) { + if (object instanceof PairwiseEquivalence) { + PairwiseEquivalence that = (PairwiseEquivalence)object; + return this.elementEquivalence.equals(that.elementEquivalence); + } + return false; + } + + public int hashCode() { + return this.elementEquivalence.hashCode() ^ 0x46A3EB07; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.elementEquivalence)); + return new StringBuilder(11 + string.length()).append(string).append(".pairwise()").toString(); + } +} diff --git a/src/com/google/common/base/Platform.java b/src/com/google/common/base/Platform.java new file mode 100644 index 0000000..c0d053d --- /dev/null +++ b/src/com/google/common/base/Platform.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.CharMatcher; +import com.google.common.base.Enums; +import com.google.common.base.Optional; +import java.lang.ref.WeakReference; + +@GwtCompatible(emulated=true) +final class Platform { + private Platform() { + } + + static long systemNanoTime() { + return System.nanoTime(); + } + + static CharMatcher precomputeCharMatcher(CharMatcher matcher) { + return matcher.precomputedInternal(); + } + + static > Optional getEnumIfPresent(Class enumClass, String value) { + WeakReference> ref = Enums.getEnumConstants(enumClass).get(value); + return ref == null ? Optional.absent() : Optional.of(enumClass.cast(ref.get())); + } +} diff --git a/src/com/google/common/base/Preconditions.java b/src/com/google/common/base/Preconditions.java new file mode 100644 index 0000000..e1d0b3e --- /dev/null +++ b/src/com/google/common/base/Preconditions.java @@ -0,0 +1,154 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Preconditions { + private Preconditions() { + } + + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + public static void checkArgument(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate, Object ... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(Preconditions.format(errorMessageTemplate, errorMessageArgs)); + } + } + + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + public static void checkState(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + public static void checkState(boolean expression, @Nullable String errorMessageTemplate, Object ... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException(Preconditions.format(errorMessageTemplate, errorMessageArgs)); + } + } + + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + public static T checkNotNull(T reference, @Nullable Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + public static T checkNotNull(T reference, @Nullable String errorMessageTemplate, Object ... errorMessageArgs) { + if (reference == null) { + throw new NullPointerException(Preconditions.format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + public static int checkElementIndex(int index, int size) { + return Preconditions.checkElementIndex(index, size, "index"); + } + + public static int checkElementIndex(int index, int size, @Nullable String desc) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(Preconditions.badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) { + return Preconditions.format("%s (%s) must not be negative", desc, index); + } + if (size < 0) { + int n = size; + throw new IllegalArgumentException(new StringBuilder(26).append("negative size: ").append(n).toString()); + } + return Preconditions.format("%s (%s) must be less than size (%s)", desc, index, size); + } + + public static int checkPositionIndex(int index, int size) { + return Preconditions.checkPositionIndex(index, size, "index"); + } + + public static int checkPositionIndex(int index, int size, @Nullable String desc) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(Preconditions.badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return Preconditions.format("%s (%s) must not be negative", desc, index); + } + if (size < 0) { + int n = size; + throw new IllegalArgumentException(new StringBuilder(26).append("negative size: ").append(n).toString()); + } + return Preconditions.format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + + public static void checkPositionIndexes(int start, int end, int size) { + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(Preconditions.badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return Preconditions.badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return Preconditions.badPositionIndex(end, size, "end index"); + } + return Preconditions.format("end index (%s) must not be less than start index (%s)", end, start); + } + + static String format(String template, Object ... args) { + int placeholderStart; + template = String.valueOf(template); + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length && (placeholderStart = template.indexOf("%s", templateStart)) != -1) { + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + return builder.toString(); + } +} diff --git a/src/com/google/common/base/Predicate.java b/src/com/google/common/base/Predicate.java new file mode 100644 index 0000000..4e297cb --- /dev/null +++ b/src/com/google/common/base/Predicate.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public interface Predicate { + public boolean apply(@Nullable T var1); + + public boolean equals(@Nullable Object var1); +} diff --git a/src/com/google/common/base/Predicates.java b/src/com/google/common/base/Predicates.java new file mode 100644 index 0000000..a126550 --- /dev/null +++ b/src/com/google/common/base/Predicates.java @@ -0,0 +1,526 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Predicates { + private static final Joiner COMMA_JOINER = Joiner.on(','); + + private Predicates() { + } + + @GwtCompatible(serializable=true) + public static Predicate alwaysTrue() { + return ObjectPredicate.ALWAYS_TRUE.withNarrowedType(); + } + + @GwtCompatible(serializable=true) + public static Predicate alwaysFalse() { + return ObjectPredicate.ALWAYS_FALSE.withNarrowedType(); + } + + @GwtCompatible(serializable=true) + public static Predicate isNull() { + return ObjectPredicate.IS_NULL.withNarrowedType(); + } + + @GwtCompatible(serializable=true) + public static Predicate notNull() { + return ObjectPredicate.NOT_NULL.withNarrowedType(); + } + + public static Predicate not(Predicate predicate) { + return new NotPredicate(predicate); + } + + public static Predicate and(Iterable> components) { + return new AndPredicate(Predicates.defensiveCopy(components)); + } + + public static Predicate and(Predicate ... components) { + return new AndPredicate(Predicates.defensiveCopy(components)); + } + + public static Predicate and(Predicate first, Predicate second) { + return new AndPredicate(Predicates.asList(Preconditions.checkNotNull(first), Preconditions.checkNotNull(second))); + } + + public static Predicate or(Iterable> components) { + return new OrPredicate(Predicates.defensiveCopy(components)); + } + + public static Predicate or(Predicate ... components) { + return new OrPredicate(Predicates.defensiveCopy(components)); + } + + public static Predicate or(Predicate first, Predicate second) { + return new OrPredicate(Predicates.asList(Preconditions.checkNotNull(first), Preconditions.checkNotNull(second))); + } + + public static Predicate equalTo(@Nullable T target) { + return target == null ? Predicates.isNull() : new IsEqualToPredicate(target); + } + + @GwtIncompatible(value="Class.isInstance") + public static Predicate instanceOf(Class clazz) { + return new InstanceOfPredicate(clazz); + } + + @GwtIncompatible(value="Class.isAssignableFrom") + @Beta + public static Predicate> assignableFrom(Class clazz) { + return new AssignableFromPredicate(clazz); + } + + public static Predicate in(Collection target) { + return new InPredicate(target); + } + + public static Predicate compose(Predicate predicate, Function function) { + return new CompositionPredicate(predicate, function); + } + + @GwtIncompatible(value="java.util.regex.Pattern") + public static Predicate containsPattern(String pattern) { + return new ContainsPatternFromStringPredicate(pattern); + } + + @GwtIncompatible(value="java.util.regex.Pattern") + public static Predicate contains(Pattern pattern) { + return new ContainsPatternPredicate(pattern); + } + + private static List> asList(Predicate first, Predicate second) { + return Arrays.asList(first, second); + } + + private static List defensiveCopy(T ... array) { + return Predicates.defensiveCopy(Arrays.asList(array)); + } + + static List defensiveCopy(Iterable iterable) { + ArrayList list = new ArrayList(); + for (T element : iterable) { + list.add(Preconditions.checkNotNull(element)); + } + return list; + } + + @GwtIncompatible(value="Only used by other GWT-incompatible code.") + private static class ContainsPatternFromStringPredicate + extends ContainsPatternPredicate { + private static final long serialVersionUID = 0L; + + ContainsPatternFromStringPredicate(String string) { + super(Pattern.compile(string)); + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.pattern.pattern())); + return new StringBuilder(28 + string.length()).append("Predicates.containsPattern(").append(string).append(")").toString(); + } + } + + @GwtIncompatible(value="Only used by other GWT-incompatible code.") + private static class ContainsPatternPredicate + implements Predicate, + Serializable { + final Pattern pattern; + private static final long serialVersionUID = 0L; + + ContainsPatternPredicate(Pattern pattern) { + this.pattern = Preconditions.checkNotNull(pattern); + } + + @Override + public boolean apply(CharSequence t) { + return this.pattern.matcher(t).find(); + } + + public int hashCode() { + return Objects.hashCode(this.pattern.pattern(), this.pattern.flags()); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof ContainsPatternPredicate) { + ContainsPatternPredicate that = (ContainsPatternPredicate)obj; + return Objects.equal(this.pattern.pattern(), that.pattern.pattern()) && Objects.equal(this.pattern.flags(), that.pattern.flags()); + } + return false; + } + + public String toString() { + String patternString = Objects.toStringHelper(this.pattern).add("pattern", this.pattern.pattern()).add("pattern.flags", this.pattern.flags()).toString(); + String string = String.valueOf(String.valueOf(patternString)); + return new StringBuilder(21 + string.length()).append("Predicates.contains(").append(string).append(")").toString(); + } + } + + private static class CompositionPredicate + implements Predicate, + Serializable { + final Predicate p; + final Function f; + private static final long serialVersionUID = 0L; + + private CompositionPredicate(Predicate p, Function f) { + this.p = Preconditions.checkNotNull(p); + this.f = Preconditions.checkNotNull(f); + } + + @Override + public boolean apply(@Nullable A a) { + return this.p.apply(this.f.apply(a)); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof CompositionPredicate) { + CompositionPredicate that = (CompositionPredicate)obj; + return this.f.equals(that.f) && this.p.equals(that.p); + } + return false; + } + + public int hashCode() { + return this.f.hashCode() ^ this.p.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.p.toString())); + String string2 = String.valueOf(String.valueOf(this.f.toString())); + return new StringBuilder(2 + string.length() + string2.length()).append(string).append("(").append(string2).append(")").toString(); + } + } + + private static class InPredicate + implements Predicate, + Serializable { + private final Collection target; + private static final long serialVersionUID = 0L; + + private InPredicate(Collection target) { + this.target = Preconditions.checkNotNull(target); + } + + @Override + public boolean apply(@Nullable T t) { + try { + return this.target.contains(t); + } + catch (NullPointerException e) { + return false; + } + catch (ClassCastException e) { + return false; + } + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof InPredicate) { + InPredicate that = (InPredicate)obj; + return this.target.equals(that.target); + } + return false; + } + + public int hashCode() { + return this.target.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.target)); + return new StringBuilder(15 + string.length()).append("Predicates.in(").append(string).append(")").toString(); + } + } + + @GwtIncompatible(value="Class.isAssignableFrom") + private static class AssignableFromPredicate + implements Predicate>, + Serializable { + private final Class clazz; + private static final long serialVersionUID = 0L; + + private AssignableFromPredicate(Class clazz) { + this.clazz = Preconditions.checkNotNull(clazz); + } + + @Override + public boolean apply(Class input) { + return this.clazz.isAssignableFrom(input); + } + + public int hashCode() { + return this.clazz.hashCode(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof AssignableFromPredicate) { + AssignableFromPredicate that = (AssignableFromPredicate)obj; + return this.clazz == that.clazz; + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.clazz.getName())); + return new StringBuilder(27 + string.length()).append("Predicates.assignableFrom(").append(string).append(")").toString(); + } + } + + @GwtIncompatible(value="Class.isInstance") + private static class InstanceOfPredicate + implements Predicate, + Serializable { + private final Class clazz; + private static final long serialVersionUID = 0L; + + private InstanceOfPredicate(Class clazz) { + this.clazz = Preconditions.checkNotNull(clazz); + } + + @Override + public boolean apply(@Nullable Object o) { + return this.clazz.isInstance(o); + } + + public int hashCode() { + return this.clazz.hashCode(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof InstanceOfPredicate) { + InstanceOfPredicate that = (InstanceOfPredicate)obj; + return this.clazz == that.clazz; + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.clazz.getName())); + return new StringBuilder(23 + string.length()).append("Predicates.instanceOf(").append(string).append(")").toString(); + } + } + + private static class IsEqualToPredicate + implements Predicate, + Serializable { + private final T target; + private static final long serialVersionUID = 0L; + + private IsEqualToPredicate(T target) { + this.target = target; + } + + @Override + public boolean apply(T t) { + return this.target.equals(t); + } + + public int hashCode() { + return this.target.hashCode(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof IsEqualToPredicate) { + IsEqualToPredicate that = (IsEqualToPredicate)obj; + return this.target.equals(that.target); + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.target)); + return new StringBuilder(20 + string.length()).append("Predicates.equalTo(").append(string).append(")").toString(); + } + } + + private static class OrPredicate + implements Predicate, + Serializable { + private final List> components; + private static final long serialVersionUID = 0L; + + private OrPredicate(List> components) { + this.components = components; + } + + @Override + public boolean apply(@Nullable T t) { + for (int i = 0; i < this.components.size(); ++i) { + if (!this.components.get(i).apply(t)) continue; + return true; + } + return false; + } + + public int hashCode() { + return this.components.hashCode() + 87855567; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof OrPredicate) { + OrPredicate that = (OrPredicate)obj; + return this.components.equals(that.components); + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(COMMA_JOINER.join(this.components))); + return new StringBuilder(15 + string.length()).append("Predicates.or(").append(string).append(")").toString(); + } + } + + private static class AndPredicate + implements Predicate, + Serializable { + private final List> components; + private static final long serialVersionUID = 0L; + + private AndPredicate(List> components) { + this.components = components; + } + + @Override + public boolean apply(@Nullable T t) { + for (int i = 0; i < this.components.size(); ++i) { + if (this.components.get(i).apply(t)) continue; + return false; + } + return true; + } + + public int hashCode() { + return this.components.hashCode() + 306654252; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof AndPredicate) { + AndPredicate that = (AndPredicate)obj; + return this.components.equals(that.components); + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(COMMA_JOINER.join(this.components))); + return new StringBuilder(16 + string.length()).append("Predicates.and(").append(string).append(")").toString(); + } + } + + private static class NotPredicate + implements Predicate, + Serializable { + final Predicate predicate; + private static final long serialVersionUID = 0L; + + NotPredicate(Predicate predicate) { + this.predicate = Preconditions.checkNotNull(predicate); + } + + @Override + public boolean apply(@Nullable T t) { + return !this.predicate.apply(t); + } + + public int hashCode() { + return ~this.predicate.hashCode(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof NotPredicate) { + NotPredicate that = (NotPredicate)obj; + return this.predicate.equals(that.predicate); + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.predicate.toString())); + return new StringBuilder(16 + string.length()).append("Predicates.not(").append(string).append(")").toString(); + } + } + + static enum ObjectPredicate implements Predicate + { + ALWAYS_TRUE{ + + @Override + public boolean apply(@Nullable Object o) { + return true; + } + + public String toString() { + return "Predicates.alwaysTrue()"; + } + } + , + ALWAYS_FALSE{ + + @Override + public boolean apply(@Nullable Object o) { + return false; + } + + public String toString() { + return "Predicates.alwaysFalse()"; + } + } + , + IS_NULL{ + + @Override + public boolean apply(@Nullable Object o) { + return o == null; + } + + public String toString() { + return "Predicates.isNull()"; + } + } + , + NOT_NULL{ + + @Override + public boolean apply(@Nullable Object o) { + return o != null; + } + + public String toString() { + return "Predicates.notNull()"; + } + }; + + + Predicate withNarrowedType() { + return this; + } + } +} diff --git a/src/com/google/common/base/Present.java b/src/com/google/common/base/Present.java new file mode 100644 index 0000000..1047845 --- /dev/null +++ b/src/com/google/common/base/Present.java @@ -0,0 +1,87 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.Collections; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +final class Present +extends Optional { + private final T reference; + private static final long serialVersionUID = 0L; + + Present(T reference) { + this.reference = reference; + } + + @Override + public boolean isPresent() { + return true; + } + + @Override + public T get() { + return this.reference; + } + + @Override + public T or(T defaultValue) { + Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)"); + return this.reference; + } + + @Override + public Optional or(Optional secondChoice) { + Preconditions.checkNotNull(secondChoice); + return this; + } + + @Override + public T or(Supplier supplier) { + Preconditions.checkNotNull(supplier); + return this.reference; + } + + @Override + public T orNull() { + return this.reference; + } + + @Override + public Set asSet() { + return Collections.singleton(this.reference); + } + + @Override + public Optional transform(Function function) { + return new Present(Preconditions.checkNotNull(function.apply(this.reference), "the Function passed to Optional.transform() must not return null.")); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Present) { + Present other = (Present)object; + return this.reference.equals(other.reference); + } + return false; + } + + @Override + public int hashCode() { + return 1502476572 + this.reference.hashCode(); + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.reference)); + return new StringBuilder(13 + string.length()).append("Optional.of(").append(string).append(")").toString(); + } +} diff --git a/src/com/google/common/base/SmallCharMatcher.java b/src/com/google/common/base/SmallCharMatcher.java new file mode 100644 index 0000000..c887db3 --- /dev/null +++ b/src/com/google/common/base/SmallCharMatcher.java @@ -0,0 +1,100 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.CharMatcher; +import java.util.BitSet; + +@GwtIncompatible(value="no precomputation is done in GWT") +final class SmallCharMatcher +extends CharMatcher.FastMatcher { + static final int MAX_SIZE = 1023; + private final char[] table; + private final boolean containsZero; + private final long filter; + private static final int C1 = -862048943; + private static final int C2 = 461845907; + private static final double DESIRED_LOAD_FACTOR = 0.5; + + private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) { + super(description); + this.table = table; + this.filter = filter; + this.containsZero = containsZero; + } + + static int smear(int hashCode) { + return 461845907 * Integer.rotateLeft(hashCode * -862048943, 15); + } + + private boolean checkFilter(int c) { + return 1L == (1L & this.filter >> c); + } + + @VisibleForTesting + static int chooseTableSize(int setSize) { + if (setSize == 1) { + return 2; + } + int tableSize = Integer.highestOneBit(setSize - 1) << 1; + while ((double)tableSize * 0.5 < (double)setSize) { + tableSize <<= 1; + } + return tableSize; + } + + static CharMatcher from(BitSet chars, String description) { + long filter = 0L; + int size = chars.cardinality(); + boolean containsZero = chars.get(0); + char[] table = new char[SmallCharMatcher.chooseTableSize(size)]; + int mask = table.length - 1; + int c = chars.nextSetBit(0); + while (c != -1) { + filter |= 1L << c; + int index = SmallCharMatcher.smear(c) & mask; + while (true) { + if (table[index] == '\u0000') break; + index = index + 1 & mask; + } + table[index] = (char)c; + c = chars.nextSetBit(c + 1); + } + return new SmallCharMatcher(table, filter, containsZero, description); + } + + @Override + public boolean matches(char c) { + int startingIndex; + if (c == '\u0000') { + return this.containsZero; + } + if (!this.checkFilter(c)) { + return false; + } + int mask = this.table.length - 1; + int index = startingIndex = SmallCharMatcher.smear(c) & mask; + do { + if (this.table[index] == '\u0000') { + return false; + } + if (this.table[index] != c) continue; + return true; + } while ((index = index + 1 & mask) != startingIndex); + return false; + } + + @Override + void setBits(BitSet table) { + if (this.containsZero) { + table.set(0); + } + for (char c : this.table) { + if (c == '\u0000') continue; + table.set(c); + } + } +} diff --git a/src/com/google/common/base/Splitter.java b/src/com/google/common/base/Splitter.java new file mode 100644 index 0000000..09798bf --- /dev/null +++ b/src/com/google/common/base/Splitter.java @@ -0,0 +1,308 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.AbstractIterator; +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.CheckReturnValue; + +@GwtCompatible(emulated=true) +public final class Splitter { + private final CharMatcher trimmer; + private final boolean omitEmptyStrings; + private final Strategy strategy; + private final int limit; + + private Splitter(Strategy strategy) { + this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE); + } + + private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) { + this.strategy = strategy; + this.omitEmptyStrings = omitEmptyStrings; + this.trimmer = trimmer; + this.limit = limit; + } + + public static Splitter on(char separator) { + return Splitter.on(CharMatcher.is(separator)); + } + + public static Splitter on(final CharMatcher separatorMatcher) { + Preconditions.checkNotNull(separatorMatcher); + return new Splitter(new Strategy(){ + + public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + return new SplittingIterator(splitter, toSplit){ + + @Override + int separatorStart(int start) { + return separatorMatcher.indexIn(this.toSplit, start); + } + + @Override + int separatorEnd(int separatorPosition) { + return separatorPosition + 1; + } + }; + } + }); + } + + public static Splitter on(final String separator) { + Preconditions.checkArgument(separator.length() != 0, "The separator may not be the empty string."); + return new Splitter(new Strategy(){ + + public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + return new SplittingIterator(splitter, toSplit){ + + @Override + public int separatorStart(int start) { + int separatorLength = separator.length(); + int last = this.toSplit.length() - separatorLength; + block0: for (int p = start; p <= last; ++p) { + for (int i = 0; i < separatorLength; ++i) { + if (this.toSplit.charAt(i + p) != separator.charAt(i)) continue block0; + } + return p; + } + return -1; + } + + @Override + public int separatorEnd(int separatorPosition) { + return separatorPosition + separator.length(); + } + }; + } + }); + } + + @GwtIncompatible(value="java.util.regex") + public static Splitter on(final Pattern separatorPattern) { + Preconditions.checkNotNull(separatorPattern); + Preconditions.checkArgument(!separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s", separatorPattern); + return new Splitter(new Strategy(){ + + public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + final Matcher matcher = separatorPattern.matcher(toSplit); + return new SplittingIterator(splitter, toSplit){ + + @Override + public int separatorStart(int start) { + return matcher.find(start) ? matcher.start() : -1; + } + + @Override + public int separatorEnd(int separatorPosition) { + return matcher.end(); + } + }; + } + }); + } + + @GwtIncompatible(value="java.util.regex") + public static Splitter onPattern(String separatorPattern) { + return Splitter.on(Pattern.compile(separatorPattern)); + } + + public static Splitter fixedLength(final int length) { + Preconditions.checkArgument(length > 0, "The length may not be less than 1"); + return new Splitter(new Strategy(){ + + public SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + return new SplittingIterator(splitter, toSplit){ + + @Override + public int separatorStart(int start) { + int nextChunkStart = start + length; + return nextChunkStart < this.toSplit.length() ? nextChunkStart : -1; + } + + @Override + public int separatorEnd(int separatorPosition) { + return separatorPosition; + } + }; + } + }); + } + + @CheckReturnValue + public Splitter omitEmptyStrings() { + return new Splitter(this.strategy, true, this.trimmer, this.limit); + } + + @CheckReturnValue + public Splitter limit(int limit) { + Preconditions.checkArgument(limit > 0, "must be greater than zero: %s", limit); + return new Splitter(this.strategy, this.omitEmptyStrings, this.trimmer, limit); + } + + @CheckReturnValue + public Splitter trimResults() { + return this.trimResults(CharMatcher.WHITESPACE); + } + + @CheckReturnValue + public Splitter trimResults(CharMatcher trimmer) { + Preconditions.checkNotNull(trimmer); + return new Splitter(this.strategy, this.omitEmptyStrings, trimmer, this.limit); + } + + public Iterable split(final CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return new Iterable(){ + + @Override + public Iterator iterator() { + return Splitter.this.splittingIterator(sequence); + } + + public String toString() { + return Joiner.on(", ").appendTo(new StringBuilder().append('['), (Iterable)this).append(']').toString(); + } + }; + } + + private Iterator splittingIterator(CharSequence sequence) { + return this.strategy.iterator(this, sequence); + } + + @Beta + public List splitToList(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + Iterator iterator = this.splittingIterator(sequence); + ArrayList result = new ArrayList(); + while (iterator.hasNext()) { + result.add(iterator.next()); + } + return Collections.unmodifiableList(result); + } + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(String separator) { + return this.withKeyValueSeparator(Splitter.on(separator)); + } + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(char separator) { + return this.withKeyValueSeparator(Splitter.on(separator)); + } + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) { + return new MapSplitter(this, keyValueSplitter); + } + + private static abstract class SplittingIterator + extends AbstractIterator { + final CharSequence toSplit; + final CharMatcher trimmer; + final boolean omitEmptyStrings; + int offset = 0; + int limit; + + abstract int separatorStart(int var1); + + abstract int separatorEnd(int var1); + + protected SplittingIterator(Splitter splitter, CharSequence toSplit) { + this.trimmer = splitter.trimmer; + this.omitEmptyStrings = splitter.omitEmptyStrings; + this.limit = splitter.limit; + this.toSplit = toSplit; + } + + @Override + protected String computeNext() { + int nextStart = this.offset; + while (this.offset != -1) { + int end; + int start = nextStart; + int separatorPosition = this.separatorStart(this.offset); + if (separatorPosition == -1) { + end = this.toSplit.length(); + this.offset = -1; + } else { + end = separatorPosition; + this.offset = this.separatorEnd(separatorPosition); + } + if (this.offset == nextStart) { + ++this.offset; + if (this.offset < this.toSplit.length()) continue; + this.offset = -1; + continue; + } + while (start < end && this.trimmer.matches(this.toSplit.charAt(start))) { + ++start; + } + while (end > start && this.trimmer.matches(this.toSplit.charAt(end - 1))) { + --end; + } + if (this.omitEmptyStrings && start == end) { + nextStart = this.offset; + continue; + } + if (this.limit == 1) { + this.offset = -1; + for (end = this.toSplit.length(); end > start && this.trimmer.matches(this.toSplit.charAt(end - 1)); --end) { + } + } else { + --this.limit; + } + return this.toSplit.subSequence(start, end).toString(); + } + return (String)this.endOfData(); + } + } + + private static interface Strategy { + public Iterator iterator(Splitter var1, CharSequence var2); + } + + @Beta + public static final class MapSplitter { + private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry"; + private final Splitter outerSplitter; + private final Splitter entrySplitter; + + private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) { + this.outerSplitter = outerSplitter; + this.entrySplitter = Preconditions.checkNotNull(entrySplitter); + } + + public Map split(CharSequence sequence) { + LinkedHashMap map = new LinkedHashMap(); + for (String entry : this.outerSplitter.split(sequence)) { + Iterator entryFields = this.entrySplitter.splittingIterator(entry); + Preconditions.checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); + String key = (String)entryFields.next(); + Preconditions.checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", key); + Preconditions.checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); + String value = (String)entryFields.next(); + map.put(key, value); + Preconditions.checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry); + } + return Collections.unmodifiableMap(map); + } + } +} diff --git a/src/com/google/common/base/StandardSystemProperty.java b/src/com/google/common/base/StandardSystemProperty.java new file mode 100644 index 0000000..66c42b3 --- /dev/null +++ b/src/com/google/common/base/StandardSystemProperty.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import javax.annotation.Nullable; + +@Beta +@GwtIncompatible(value="java.lang.System#getProperty") +public enum StandardSystemProperty { + JAVA_VERSION("java.version"), + JAVA_VENDOR("java.vendor"), + JAVA_VENDOR_URL("java.vendor.url"), + JAVA_HOME("java.home"), + JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"), + JAVA_VM_SPECIFICATION_VENDOR("java.vm.specification.vendor"), + JAVA_VM_SPECIFICATION_NAME("java.vm.specification.name"), + JAVA_VM_VERSION("java.vm.version"), + JAVA_VM_VENDOR("java.vm.vendor"), + JAVA_VM_NAME("java.vm.name"), + JAVA_SPECIFICATION_VERSION("java.specification.version"), + JAVA_SPECIFICATION_VENDOR("java.specification.vendor"), + JAVA_SPECIFICATION_NAME("java.specification.name"), + JAVA_CLASS_VERSION("java.class.version"), + JAVA_CLASS_PATH("java.class.path"), + JAVA_LIBRARY_PATH("java.library.path"), + JAVA_IO_TMPDIR("java.io.tmpdir"), + JAVA_COMPILER("java.compiler"), + JAVA_EXT_DIRS("java.ext.dirs"), + OS_NAME("os.name"), + OS_ARCH("os.arch"), + OS_VERSION("os.version"), + FILE_SEPARATOR("file.separator"), + PATH_SEPARATOR("path.separator"), + LINE_SEPARATOR("line.separator"), + USER_NAME("user.name"), + USER_HOME("user.home"), + USER_DIR("user.dir"); + + private final String key; + + private StandardSystemProperty(String key) { + this.key = key; + } + + public String key() { + return this.key; + } + + @Nullable + public String value() { + return System.getProperty(this.key); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.key())); + String string2 = String.valueOf(String.valueOf(this.value())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append("=").append(string2).toString(); + } +} diff --git a/src/com/google/common/base/Stopwatch.java b/src/com/google/common/base/Stopwatch.java new file mode 100644 index 0000000..d00acdf --- /dev/null +++ b/src/com/google/common/base/Stopwatch.java @@ -0,0 +1,136 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Ticker; +import java.util.concurrent.TimeUnit; + +@Beta +@GwtCompatible(emulated=true) +public final class Stopwatch { + private final Ticker ticker; + private boolean isRunning; + private long elapsedNanos; + private long startTick; + + public static Stopwatch createUnstarted() { + return new Stopwatch(); + } + + public static Stopwatch createUnstarted(Ticker ticker) { + return new Stopwatch(ticker); + } + + public static Stopwatch createStarted() { + return new Stopwatch().start(); + } + + public static Stopwatch createStarted(Ticker ticker) { + return new Stopwatch(ticker).start(); + } + + @Deprecated + Stopwatch() { + this(Ticker.systemTicker()); + } + + @Deprecated + Stopwatch(Ticker ticker) { + this.ticker = Preconditions.checkNotNull(ticker, "ticker"); + } + + public boolean isRunning() { + return this.isRunning; + } + + public Stopwatch start() { + Preconditions.checkState(!this.isRunning, "This stopwatch is already running."); + this.isRunning = true; + this.startTick = this.ticker.read(); + return this; + } + + public Stopwatch stop() { + long tick = this.ticker.read(); + Preconditions.checkState(this.isRunning, "This stopwatch is already stopped."); + this.isRunning = false; + this.elapsedNanos += tick - this.startTick; + return this; + } + + public Stopwatch reset() { + this.elapsedNanos = 0L; + this.isRunning = false; + return this; + } + + private long elapsedNanos() { + return this.isRunning ? this.ticker.read() - this.startTick + this.elapsedNanos : this.elapsedNanos; + } + + public long elapsed(TimeUnit desiredUnit) { + return desiredUnit.convert(this.elapsedNanos(), TimeUnit.NANOSECONDS); + } + + @GwtIncompatible(value="String.format()") + public String toString() { + long nanos = this.elapsedNanos(); + TimeUnit unit = Stopwatch.chooseUnit(nanos); + double value = (double)nanos / (double)TimeUnit.NANOSECONDS.convert(1L, unit); + return String.format("%.4g %s", value, Stopwatch.abbreviate(unit)); + } + + private static TimeUnit chooseUnit(long nanos) { + if (TimeUnit.DAYS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.DAYS; + } + if (TimeUnit.HOURS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.HOURS; + } + if (TimeUnit.MINUTES.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MINUTES; + } + if (TimeUnit.SECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.SECONDS; + } + if (TimeUnit.MILLISECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MILLISECONDS; + } + if (TimeUnit.MICROSECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MICROSECONDS; + } + return TimeUnit.NANOSECONDS; + } + + private static String abbreviate(TimeUnit unit) { + switch (unit) { + case NANOSECONDS: { + return "ns"; + } + case MICROSECONDS: { + return "\u03bcs"; + } + case MILLISECONDS: { + return "ms"; + } + case SECONDS: { + return "s"; + } + case MINUTES: { + return "min"; + } + case HOURS: { + return "h"; + } + case DAYS: { + return "d"; + } + } + throw new AssertionError(); + } +} diff --git a/src/com/google/common/base/Strings.java b/src/com/google/common/base/Strings.java new file mode 100644 index 0000000..3ab343a --- /dev/null +++ b/src/com/google/common/base/Strings.java @@ -0,0 +1,108 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Strings { + private Strings() { + } + + public static String nullToEmpty(@Nullable String string) { + return string == null ? "" : string; + } + + @Nullable + public static String emptyToNull(@Nullable String string) { + return Strings.isNullOrEmpty(string) ? null : string; + } + + public static boolean isNullOrEmpty(@Nullable String string) { + return string == null || string.length() == 0; + } + + public static String padStart(String string, int minLength, char padChar) { + Preconditions.checkNotNull(string); + if (string.length() >= minLength) { + return string; + } + StringBuilder sb = new StringBuilder(minLength); + for (int i = string.length(); i < minLength; ++i) { + sb.append(padChar); + } + sb.append(string); + return sb.toString(); + } + + public static String padEnd(String string, int minLength, char padChar) { + Preconditions.checkNotNull(string); + if (string.length() >= minLength) { + return string; + } + StringBuilder sb = new StringBuilder(minLength); + sb.append(string); + for (int i = string.length(); i < minLength; ++i) { + sb.append(padChar); + } + return sb.toString(); + } + + public static String repeat(String string, int count) { + int n; + Preconditions.checkNotNull(string); + if (count <= 1) { + Preconditions.checkArgument(count >= 0, "invalid count: %s", count); + return count == 0 ? "" : string; + } + int len = string.length(); + long longSize = (long)len * (long)count; + int size = (int)longSize; + if ((long)size != longSize) { + long l = longSize; + throw new ArrayIndexOutOfBoundsException(new StringBuilder(51).append("Required array size too large: ").append(l).toString()); + } + char[] array = new char[size]; + string.getChars(0, len, array, 0); + for (n = len; n < size - n; n <<= 1) { + System.arraycopy(array, 0, array, n, n); + } + System.arraycopy(array, 0, array, n, size - n); + return new String(array); + } + + public static String commonPrefix(CharSequence a, CharSequence b) { + int p; + Preconditions.checkNotNull(a); + Preconditions.checkNotNull(b); + int maxPrefixLength = Math.min(a.length(), b.length()); + for (p = 0; p < maxPrefixLength && a.charAt(p) == b.charAt(p); ++p) { + } + if (Strings.validSurrogatePairAt(a, p - 1) || Strings.validSurrogatePairAt(b, p - 1)) { + --p; + } + return a.subSequence(0, p).toString(); + } + + public static String commonSuffix(CharSequence a, CharSequence b) { + int s; + Preconditions.checkNotNull(a); + Preconditions.checkNotNull(b); + int maxSuffixLength = Math.min(a.length(), b.length()); + for (s = 0; s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1); ++s) { + } + if (Strings.validSurrogatePairAt(a, a.length() - s - 1) || Strings.validSurrogatePairAt(b, b.length() - s - 1)) { + --s; + } + return a.subSequence(a.length() - s, a.length()).toString(); + } + + @VisibleForTesting + static boolean validSurrogatePairAt(CharSequence string, int index) { + return index >= 0 && index <= string.length() - 2 && Character.isHighSurrogate(string.charAt(index)) && Character.isLowSurrogate(string.charAt(index + 1)); + } +} diff --git a/src/com/google/common/base/Supplier.java b/src/com/google/common/base/Supplier.java new file mode 100644 index 0000000..70cbabf --- /dev/null +++ b/src/com/google/common/base/Supplier.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public interface Supplier { + public T get(); +} diff --git a/src/com/google/common/base/Suppliers.java b/src/com/google/common/base/Suppliers.java new file mode 100644 index 0000000..e6affa3 --- /dev/null +++ b/src/com/google/common/base/Suppliers.java @@ -0,0 +1,248 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Platform; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Suppliers { + private Suppliers() { + } + + public static Supplier compose(Function function, Supplier supplier) { + Preconditions.checkNotNull(function); + Preconditions.checkNotNull(supplier); + return new SupplierComposition(function, supplier); + } + + public static Supplier memoize(Supplier delegate) { + return delegate instanceof MemoizingSupplier ? delegate : new MemoizingSupplier(Preconditions.checkNotNull(delegate)); + } + + public static Supplier memoizeWithExpiration(Supplier delegate, long duration, TimeUnit unit) { + return new ExpiringMemoizingSupplier(delegate, duration, unit); + } + + public static Supplier ofInstance(@Nullable T instance) { + return new SupplierOfInstance(instance); + } + + public static Supplier synchronizedSupplier(Supplier delegate) { + return new ThreadSafeSupplier(Preconditions.checkNotNull(delegate)); + } + + @Beta + public static Function, T> supplierFunction() { + SupplierFunctionImpl sf = SupplierFunctionImpl.INSTANCE; + return sf; + } + + private static enum SupplierFunctionImpl implements SupplierFunction + { + INSTANCE; + + + @Override + public Object apply(Supplier input) { + return input.get(); + } + + public String toString() { + return "Suppliers.supplierFunction()"; + } + } + + private static interface SupplierFunction + extends Function, T> { + } + + private static class ThreadSafeSupplier + implements Supplier, + Serializable { + final Supplier delegate; + private static final long serialVersionUID = 0L; + + ThreadSafeSupplier(Supplier delegate) { + this.delegate = delegate; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T get() { + Supplier supplier = this.delegate; + synchronized (supplier) { + return this.delegate.get(); + } + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.delegate)); + return new StringBuilder(32 + string.length()).append("Suppliers.synchronizedSupplier(").append(string).append(")").toString(); + } + } + + private static class SupplierOfInstance + implements Supplier, + Serializable { + final T instance; + private static final long serialVersionUID = 0L; + + SupplierOfInstance(@Nullable T instance) { + this.instance = instance; + } + + @Override + public T get() { + return this.instance; + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof SupplierOfInstance) { + SupplierOfInstance that = (SupplierOfInstance)obj; + return Objects.equal(this.instance, that.instance); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.instance); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.instance)); + return new StringBuilder(22 + string.length()).append("Suppliers.ofInstance(").append(string).append(")").toString(); + } + } + + @VisibleForTesting + static class ExpiringMemoizingSupplier + implements Supplier, + Serializable { + final Supplier delegate; + final long durationNanos; + volatile transient T value; + volatile transient long expirationNanos; + private static final long serialVersionUID = 0L; + + ExpiringMemoizingSupplier(Supplier delegate, long duration, TimeUnit unit) { + this.delegate = Preconditions.checkNotNull(delegate); + this.durationNanos = unit.toNanos(duration); + Preconditions.checkArgument(duration > 0L); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T get() { + long nanos = this.expirationNanos; + long now = Platform.systemNanoTime(); + if (nanos == 0L || now - nanos >= 0L) { + ExpiringMemoizingSupplier expiringMemoizingSupplier = this; + synchronized (expiringMemoizingSupplier) { + if (nanos == this.expirationNanos) { + T t = this.delegate.get(); + this.value = t; + nanos = now + this.durationNanos; + this.expirationNanos = nanos == 0L ? 1L : nanos; + return t; + } + } + } + return this.value; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.delegate)); + long l = this.durationNanos; + return new StringBuilder(62 + string.length()).append("Suppliers.memoizeWithExpiration(").append(string).append(", ").append(l).append(", NANOS)").toString(); + } + } + + @VisibleForTesting + static class MemoizingSupplier + implements Supplier, + Serializable { + final Supplier delegate; + volatile transient boolean initialized; + transient T value; + private static final long serialVersionUID = 0L; + + MemoizingSupplier(Supplier delegate) { + this.delegate = delegate; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T get() { + if (!this.initialized) { + MemoizingSupplier memoizingSupplier = this; + synchronized (memoizingSupplier) { + if (!this.initialized) { + T t = this.delegate.get(); + this.value = t; + this.initialized = true; + return t; + } + } + } + return this.value; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.delegate)); + return new StringBuilder(19 + string.length()).append("Suppliers.memoize(").append(string).append(")").toString(); + } + } + + private static class SupplierComposition + implements Supplier, + Serializable { + final Function function; + final Supplier supplier; + private static final long serialVersionUID = 0L; + + SupplierComposition(Function function, Supplier supplier) { + this.function = function; + this.supplier = supplier; + } + + @Override + public T get() { + return this.function.apply(this.supplier.get()); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof SupplierComposition) { + SupplierComposition that = (SupplierComposition)obj; + return this.function.equals(that.function) && this.supplier.equals(that.supplier); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.function, this.supplier); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.function)); + String string2 = String.valueOf(String.valueOf(this.supplier)); + return new StringBuilder(21 + string.length() + string2.length()).append("Suppliers.compose(").append(string).append(", ").append(string2).append(")").toString(); + } + } +} diff --git a/src/com/google/common/base/Throwables.java b/src/com/google/common/base/Throwables.java new file mode 100644 index 0000000..7b2e300 --- /dev/null +++ b/src/com/google/common/base/Throwables.java @@ -0,0 +1,70 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; + +public final class Throwables { + private Throwables() { + } + + public static void propagateIfInstanceOf(@Nullable Throwable throwable, Class declaredType) throws X { + if (throwable != null && declaredType.isInstance(throwable)) { + throw (Throwable)declaredType.cast(throwable); + } + } + + public static void propagateIfPossible(@Nullable Throwable throwable) { + Throwables.propagateIfInstanceOf(throwable, Error.class); + Throwables.propagateIfInstanceOf(throwable, RuntimeException.class); + } + + public static void propagateIfPossible(@Nullable Throwable throwable, Class declaredType) throws X { + Throwables.propagateIfInstanceOf(throwable, declaredType); + Throwables.propagateIfPossible(throwable); + } + + public static void propagateIfPossible(@Nullable Throwable throwable, Class declaredType1, Class declaredType2) throws X1, X2 { + Preconditions.checkNotNull(declaredType2); + Throwables.propagateIfInstanceOf(throwable, declaredType1); + Throwables.propagateIfPossible(throwable, declaredType2); + } + + public static RuntimeException propagate(Throwable throwable) { + Throwables.propagateIfPossible(Preconditions.checkNotNull(throwable)); + throw new RuntimeException(throwable); + } + + public static Throwable getRootCause(Throwable throwable) { + Throwable cause; + while ((cause = throwable.getCause()) != null) { + throwable = cause; + } + return throwable; + } + + @Beta + public static List getCausalChain(Throwable throwable) { + Preconditions.checkNotNull(throwable); + ArrayList causes = new ArrayList(4); + while (throwable != null) { + causes.add(throwable); + throwable = throwable.getCause(); + } + return Collections.unmodifiableList(causes); + } + + public static String getStackTraceAsString(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } +} diff --git a/src/com/google/common/base/Ticker.java b/src/com/google/common/base/Ticker.java new file mode 100644 index 0000000..ceeacd3 --- /dev/null +++ b/src/com/google/common/base/Ticker.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Platform; + +@Beta +@GwtCompatible +public abstract class Ticker { + private static final Ticker SYSTEM_TICKER = new Ticker(){ + + @Override + public long read() { + return Platform.systemNanoTime(); + } + }; + + protected Ticker() { + } + + public abstract long read(); + + public static Ticker systemTicker() { + return SYSTEM_TICKER; + } +} diff --git a/src/com/google/common/base/Utf8.java b/src/com/google/common/base/Utf8.java new file mode 100644 index 0000000..56ee509 --- /dev/null +++ b/src/com/google/common/base/Utf8.java @@ -0,0 +1,104 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; + +@Beta +@GwtCompatible +public final class Utf8 { + public static int encodedLength(CharSequence sequence) { + int i; + int utf16Length; + int utf8Length = utf16Length = sequence.length(); + for (i = 0; i < utf16Length && sequence.charAt(i) < '\u0080'; ++i) { + } + while (i < utf16Length) { + char c = sequence.charAt(i); + if (c < '\u0800') { + utf8Length += 127 - c >>> 31; + } else { + utf8Length += Utf8.encodedLengthGeneral(sequence, i); + break; + } + ++i; + } + if (utf8Length < utf16Length) { + long l = (long)utf8Length + 0x100000000L; + throw new IllegalArgumentException(new StringBuilder(54).append("UTF-8 length does not fit in int: ").append(l).toString()); + } + return utf8Length; + } + + private static int encodedLengthGeneral(CharSequence sequence, int start) { + int utf16Length = sequence.length(); + int utf8Length = 0; + for (int i = start; i < utf16Length; ++i) { + char c = sequence.charAt(i); + if (c < '\u0800') { + utf8Length += 127 - c >>> 31; + continue; + } + utf8Length += 2; + if ('\ud800' > c || c > '\udfff') continue; + int cp = Character.codePointAt(sequence, i); + if (cp < 65536) { + int n = i; + throw new IllegalArgumentException(new StringBuilder(39).append("Unpaired surrogate at index ").append(n).toString()); + } + ++i; + } + return utf8Length; + } + + public static boolean isWellFormed(byte[] bytes) { + return Utf8.isWellFormed(bytes, 0, bytes.length); + } + + public static boolean isWellFormed(byte[] bytes, int off, int len) { + int end = off + len; + Preconditions.checkPositionIndexes(off, end, bytes.length); + for (int i = off; i < end; ++i) { + if (bytes[i] >= 0) continue; + return Utf8.isWellFormedSlowPath(bytes, i, end); + } + return true; + } + + private static boolean isWellFormedSlowPath(byte[] bytes, int off, int end) { + int index = off; + while (true) { + byte byte2; + byte byte1; + if (index >= end) { + return true; + } + if ((byte1 = bytes[index++]) >= 0) continue; + if (byte1 < -32) { + if (index == end) { + return false; + } + if (byte1 >= -62 && bytes[index++] <= -65) continue; + return false; + } + if (byte1 < -16) { + if (index + 1 >= end) { + return false; + } + if (!((byte2 = bytes[index++]) > -65 || byte1 == -32 && byte2 < -96 || byte1 == -19 && -96 <= byte2) && bytes[index++] <= -65) continue; + return false; + } + if (index + 2 >= end) { + return false; + } + if ((byte2 = bytes[index++]) > -65 || (byte1 << 28) + (byte2 - -112) >> 30 != 0 || bytes[index++] > -65 || bytes[index++] > -65) break; + } + return false; + } + + private Utf8() { + } +} diff --git a/src/com/google/common/base/Verify.java b/src/com/google/common/base/Verify.java new file mode 100644 index 0000000..46bd27c --- /dev/null +++ b/src/com/google/common/base/Verify.java @@ -0,0 +1,38 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.VerifyException; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class Verify { + public static void verify(boolean expression) { + if (!expression) { + throw new VerifyException(); + } + } + + public static void verify(boolean expression, @Nullable String errorMessageTemplate, Object ... errorMessageArgs) { + if (!expression) { + throw new VerifyException(Preconditions.format(errorMessageTemplate, errorMessageArgs)); + } + } + + public static T verifyNotNull(@Nullable T reference) { + return Verify.verifyNotNull(reference, "expected a non-null reference", new Object[0]); + } + + public static T verifyNotNull(@Nullable T reference, @Nullable String errorMessageTemplate, Object ... errorMessageArgs) { + Verify.verify(reference != null, errorMessageTemplate, errorMessageArgs); + return reference; + } + + private Verify() { + } +} diff --git a/src/com/google/common/base/VerifyException.java b/src/com/google/common/base/VerifyException.java new file mode 100644 index 0000000..0e03d9b --- /dev/null +++ b/src/com/google/common/base/VerifyException.java @@ -0,0 +1,20 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public class VerifyException +extends RuntimeException { + public VerifyException() { + } + + public VerifyException(@Nullable String message) { + super(message); + } +} diff --git a/src/com/google/common/base/internal/Finalizer.java b/src/com/google/common/base/internal/Finalizer.java new file mode 100644 index 0000000..415ea71 --- /dev/null +++ b/src/com/google/common/base/internal/Finalizer.java @@ -0,0 +1,107 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.base.internal; + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class Finalizer +implements Runnable { + private static final Logger logger = Logger.getLogger(Finalizer.class.getName()); + private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference"; + private final WeakReference> finalizableReferenceClassReference; + private final PhantomReference frqReference; + private final ReferenceQueue queue; + private static final Field inheritableThreadLocals = Finalizer.getInheritableThreadLocalsField(); + + public static void startFinalizer(Class finalizableReferenceClass, ReferenceQueue queue, PhantomReference frqReference) { + if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) { + throw new IllegalArgumentException("Expected com.google.common.base.FinalizableReference."); + } + Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference); + Thread thread = new Thread(finalizer); + thread.setName(Finalizer.class.getName()); + thread.setDaemon(true); + try { + if (inheritableThreadLocals != null) { + inheritableThreadLocals.set(thread, null); + } + } + catch (Throwable t) { + logger.log(Level.INFO, "Failed to clear thread local values inherited by reference finalizer thread.", t); + } + thread.start(); + } + + private Finalizer(Class finalizableReferenceClass, ReferenceQueue queue, PhantomReference frqReference) { + this.queue = queue; + this.finalizableReferenceClassReference = new WeakReference(finalizableReferenceClass); + this.frqReference = frqReference; + } + + @Override + public void run() { + while (true) { + try { + while (this.cleanUp(this.queue.remove())) { + } + } + catch (InterruptedException interruptedException) { + continue; + } + break; + } + } + + private boolean cleanUp(Reference reference) { + Method finalizeReferentMethod = this.getFinalizeReferentMethod(); + if (finalizeReferentMethod == null) { + return false; + } + do { + reference.clear(); + if (reference == this.frqReference) { + return false; + } + try { + finalizeReferentMethod.invoke(reference, new Object[0]); + } + catch (Throwable t) { + logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + } + } while ((reference = this.queue.poll()) != null); + return true; + } + + private Method getFinalizeReferentMethod() { + Class finalizableReferenceClass = (Class)this.finalizableReferenceClassReference.get(); + if (finalizableReferenceClass == null) { + return null; + } + try { + return finalizableReferenceClass.getMethod("finalizeReferent", new Class[0]); + } + catch (NoSuchMethodException e) { + throw new AssertionError((Object)e); + } + } + + public static Field getInheritableThreadLocalsField() { + try { + Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals"); + inheritableThreadLocals.setAccessible(true); + return inheritableThreadLocals; + } + catch (Throwable t) { + logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will inherit thread local values."); + return null; + } + } +} diff --git a/src/com/google/common/base/package-info.java b/src/com/google/common/base/package-info.java new file mode 100644 index 0000000..bb0dd62 --- /dev/null +++ b/src/com/google/common/base/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.base; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/cache/AbstractCache.java b/src/com/google/common/cache/AbstractCache.java new file mode 100644 index 0000000..84d176c --- /dev/null +++ b/src/com/google/common/cache/AbstractCache.java @@ -0,0 +1,160 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.cache.LongAddable; +import com.google.common.cache.LongAddables; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + +@Beta +@GwtCompatible +public abstract class AbstractCache +implements Cache { + protected AbstractCache() { + } + + @Override + public V get(K key, Callable valueLoader) throws ExecutionException { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableMap getAllPresent(Iterable keys) { + LinkedHashMap result = Maps.newLinkedHashMap(); + for (Object key : keys) { + if (result.containsKey(key)) continue; + Object castKey = key; + Object value = this.getIfPresent(key); + if (value == null) continue; + result.put(castKey, value); + } + return ImmutableMap.copyOf(result); + } + + @Override + public void put(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(Map m) { + for (Map.Entry entry : m.entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void cleanUp() { + } + + @Override + public long size() { + throw new UnsupportedOperationException(); + } + + @Override + public void invalidate(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public void invalidateAll(Iterable keys) { + for (Object key : keys) { + this.invalidate(key); + } + } + + @Override + public void invalidateAll() { + throw new UnsupportedOperationException(); + } + + @Override + public CacheStats stats() { + throw new UnsupportedOperationException(); + } + + @Override + public ConcurrentMap asMap() { + throw new UnsupportedOperationException(); + } + + @Beta + public static final class SimpleStatsCounter + implements StatsCounter { + private final LongAddable hitCount = LongAddables.create(); + private final LongAddable missCount = LongAddables.create(); + private final LongAddable loadSuccessCount = LongAddables.create(); + private final LongAddable loadExceptionCount = LongAddables.create(); + private final LongAddable totalLoadTime = LongAddables.create(); + private final LongAddable evictionCount = LongAddables.create(); + + @Override + public void recordHits(int count) { + this.hitCount.add(count); + } + + @Override + public void recordMisses(int count) { + this.missCount.add(count); + } + + @Override + public void recordLoadSuccess(long loadTime) { + this.loadSuccessCount.increment(); + this.totalLoadTime.add(loadTime); + } + + @Override + public void recordLoadException(long loadTime) { + this.loadExceptionCount.increment(); + this.totalLoadTime.add(loadTime); + } + + @Override + public void recordEviction() { + this.evictionCount.increment(); + } + + @Override + public CacheStats snapshot() { + return new CacheStats(this.hitCount.sum(), this.missCount.sum(), this.loadSuccessCount.sum(), this.loadExceptionCount.sum(), this.totalLoadTime.sum(), this.evictionCount.sum()); + } + + public void incrementBy(StatsCounter other) { + CacheStats otherStats = other.snapshot(); + this.hitCount.add(otherStats.hitCount()); + this.missCount.add(otherStats.missCount()); + this.loadSuccessCount.add(otherStats.loadSuccessCount()); + this.loadExceptionCount.add(otherStats.loadExceptionCount()); + this.totalLoadTime.add(otherStats.totalLoadTime()); + this.evictionCount.add(otherStats.evictionCount()); + } + } + + @Beta + public static interface StatsCounter { + public void recordHits(int var1); + + public void recordMisses(int var1); + + public void recordLoadSuccess(long var1); + + public void recordLoadException(long var1); + + public void recordEviction(); + + public CacheStats snapshot(); + } +} diff --git a/src/com/google/common/cache/AbstractLoadingCache.java b/src/com/google/common/cache/AbstractLoadingCache.java new file mode 100644 index 0000000..bda1535 --- /dev/null +++ b/src/com/google/common/cache/AbstractLoadingCache.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.cache.AbstractCache; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.util.LinkedHashMap; +import java.util.concurrent.ExecutionException; + +@Beta +public abstract class AbstractLoadingCache +extends AbstractCache +implements LoadingCache { + protected AbstractLoadingCache() { + } + + @Override + public V getUnchecked(K key) { + try { + return this.get(key); + } + catch (ExecutionException e) { + throw new UncheckedExecutionException(e.getCause()); + } + } + + @Override + public ImmutableMap getAll(Iterable keys) throws ExecutionException { + LinkedHashMap result = Maps.newLinkedHashMap(); + for (K key : keys) { + if (result.containsKey(key)) continue; + result.put(key, this.get(key)); + } + return ImmutableMap.copyOf(result); + } + + @Override + public final V apply(K key) { + return this.getUnchecked(key); + } + + @Override + public void refresh(K key) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/cache/Cache.java b/src/com/google/common/cache/Cache.java new file mode 100644 index 0000000..6bf3c93 --- /dev/null +++ b/src/com/google/common/cache/Cache.java @@ -0,0 +1,43 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.cache.CacheStats; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public interface Cache { + @Nullable + public V getIfPresent(Object var1); + + public V get(K var1, Callable var2) throws ExecutionException; + + public ImmutableMap getAllPresent(Iterable var1); + + public void put(K var1, V var2); + + public void putAll(Map var1); + + public void invalidate(Object var1); + + public void invalidateAll(Iterable var1); + + public void invalidateAll(); + + public long size(); + + public CacheStats stats(); + + public ConcurrentMap asMap(); + + public void cleanUp(); +} diff --git a/src/com/google/common/cache/CacheBuilder.java b/src/com/google/common/cache/CacheBuilder.java new file mode 100644 index 0000000..bd99385 --- /dev/null +++ b/src/com/google/common/cache/CacheBuilder.java @@ -0,0 +1,402 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.Equivalence; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.base.Ticker; +import com.google.common.cache.AbstractCache; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilderSpec; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheStats; +import com.google.common.cache.LoadingCache; +import com.google.common.cache.LocalCache; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; +import com.google.common.cache.Weigher; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.CheckReturnValue; + +@GwtCompatible(emulated=true) +public final class CacheBuilder { + private static final int DEFAULT_INITIAL_CAPACITY = 16; + private static final int DEFAULT_CONCURRENCY_LEVEL = 4; + private static final int DEFAULT_EXPIRATION_NANOS = 0; + private static final int DEFAULT_REFRESH_NANOS = 0; + static final Supplier NULL_STATS_COUNTER = Suppliers.ofInstance(new AbstractCache.StatsCounter(){ + + @Override + public void recordHits(int count) { + } + + @Override + public void recordMisses(int count) { + } + + @Override + public void recordLoadSuccess(long loadTime) { + } + + @Override + public void recordLoadException(long loadTime) { + } + + @Override + public void recordEviction() { + } + + @Override + public CacheStats snapshot() { + return EMPTY_STATS; + } + }); + static final CacheStats EMPTY_STATS = new CacheStats(0L, 0L, 0L, 0L, 0L, 0L); + static final Supplier CACHE_STATS_COUNTER = new Supplier(){ + + @Override + public AbstractCache.StatsCounter get() { + return new AbstractCache.SimpleStatsCounter(); + } + }; + static final Ticker NULL_TICKER = new Ticker(){ + + @Override + public long read() { + return 0L; + } + }; + private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName()); + static final int UNSET_INT = -1; + boolean strictParsing = true; + int initialCapacity = -1; + int concurrencyLevel = -1; + long maximumSize = -1L; + long maximumWeight = -1L; + Weigher weigher; + LocalCache.Strength keyStrength; + LocalCache.Strength valueStrength; + long expireAfterWriteNanos = -1L; + long expireAfterAccessNanos = -1L; + long refreshNanos = -1L; + Equivalence keyEquivalence; + Equivalence valueEquivalence; + RemovalListener removalListener; + Ticker ticker; + Supplier statsCounterSupplier = NULL_STATS_COUNTER; + + CacheBuilder() { + } + + public static CacheBuilder newBuilder() { + return new CacheBuilder(); + } + + @Beta + @GwtIncompatible(value="To be supported") + public static CacheBuilder from(CacheBuilderSpec spec) { + return spec.toCacheBuilder().lenientParsing(); + } + + @Beta + @GwtIncompatible(value="To be supported") + public static CacheBuilder from(String spec) { + return CacheBuilder.from(CacheBuilderSpec.parse(spec)); + } + + @GwtIncompatible(value="To be supported") + CacheBuilder lenientParsing() { + this.strictParsing = false; + return this; + } + + @GwtIncompatible(value="To be supported") + CacheBuilder keyEquivalence(Equivalence equivalence) { + Preconditions.checkState(this.keyEquivalence == null, "key equivalence was already set to %s", this.keyEquivalence); + this.keyEquivalence = Preconditions.checkNotNull(equivalence); + return this; + } + + Equivalence getKeyEquivalence() { + return MoreObjects.firstNonNull(this.keyEquivalence, this.getKeyStrength().defaultEquivalence()); + } + + @GwtIncompatible(value="To be supported") + CacheBuilder valueEquivalence(Equivalence equivalence) { + Preconditions.checkState(this.valueEquivalence == null, "value equivalence was already set to %s", this.valueEquivalence); + this.valueEquivalence = Preconditions.checkNotNull(equivalence); + return this; + } + + Equivalence getValueEquivalence() { + return MoreObjects.firstNonNull(this.valueEquivalence, this.getValueStrength().defaultEquivalence()); + } + + public CacheBuilder initialCapacity(int initialCapacity) { + Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", this.initialCapacity); + Preconditions.checkArgument(initialCapacity >= 0); + this.initialCapacity = initialCapacity; + return this; + } + + int getInitialCapacity() { + return this.initialCapacity == -1 ? 16 : this.initialCapacity; + } + + public CacheBuilder concurrencyLevel(int concurrencyLevel) { + Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", this.concurrencyLevel); + Preconditions.checkArgument(concurrencyLevel > 0); + this.concurrencyLevel = concurrencyLevel; + return this; + } + + int getConcurrencyLevel() { + return this.concurrencyLevel == -1 ? 4 : this.concurrencyLevel; + } + + public CacheBuilder maximumSize(long size) { + Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize); + Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight); + Preconditions.checkState(this.weigher == null, "maximum size can not be combined with weigher"); + Preconditions.checkArgument(size >= 0L, "maximum size must not be negative"); + this.maximumSize = size; + return this; + } + + @GwtIncompatible(value="To be supported") + public CacheBuilder maximumWeight(long weight) { + Preconditions.checkState(this.maximumWeight == -1L, "maximum weight was already set to %s", this.maximumWeight); + Preconditions.checkState(this.maximumSize == -1L, "maximum size was already set to %s", this.maximumSize); + this.maximumWeight = weight; + Preconditions.checkArgument(weight >= 0L, "maximum weight must not be negative"); + return this; + } + + @GwtIncompatible(value="To be supported") + public CacheBuilder weigher(Weigher weigher) { + Preconditions.checkState(this.weigher == null); + if (this.strictParsing) { + Preconditions.checkState(this.maximumSize == -1L, "weigher can not be combined with maximum size", this.maximumSize); + } + CacheBuilder me = this; + me.weigher = Preconditions.checkNotNull(weigher); + return me; + } + + long getMaximumWeight() { + if (this.expireAfterWriteNanos == 0L || this.expireAfterAccessNanos == 0L) { + return 0L; + } + return this.weigher == null ? this.maximumSize : this.maximumWeight; + } + + Weigher getWeigher() { + return MoreObjects.firstNonNull(this.weigher, OneWeigher.INSTANCE); + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public CacheBuilder weakKeys() { + return this.setKeyStrength(LocalCache.Strength.WEAK); + } + + CacheBuilder setKeyStrength(LocalCache.Strength strength) { + Preconditions.checkState(this.keyStrength == null, "Key strength was already set to %s", new Object[]{this.keyStrength}); + this.keyStrength = Preconditions.checkNotNull(strength); + return this; + } + + LocalCache.Strength getKeyStrength() { + return MoreObjects.firstNonNull(this.keyStrength, LocalCache.Strength.STRONG); + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public CacheBuilder weakValues() { + return this.setValueStrength(LocalCache.Strength.WEAK); + } + + @GwtIncompatible(value="java.lang.ref.SoftReference") + public CacheBuilder softValues() { + return this.setValueStrength(LocalCache.Strength.SOFT); + } + + CacheBuilder setValueStrength(LocalCache.Strength strength) { + Preconditions.checkState(this.valueStrength == null, "Value strength was already set to %s", new Object[]{this.valueStrength}); + this.valueStrength = Preconditions.checkNotNull(strength); + return this; + } + + LocalCache.Strength getValueStrength() { + return MoreObjects.firstNonNull(this.valueStrength, LocalCache.Strength.STRONG); + } + + public CacheBuilder expireAfterWrite(long duration, TimeUnit unit) { + Preconditions.checkState(this.expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", this.expireAfterWriteNanos); + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[]{duration, unit}); + this.expireAfterWriteNanos = unit.toNanos(duration); + return this; + } + + long getExpireAfterWriteNanos() { + return this.expireAfterWriteNanos == -1L ? 0L : this.expireAfterWriteNanos; + } + + public CacheBuilder expireAfterAccess(long duration, TimeUnit unit) { + Preconditions.checkState(this.expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", this.expireAfterAccessNanos); + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[]{duration, unit}); + this.expireAfterAccessNanos = unit.toNanos(duration); + return this; + } + + long getExpireAfterAccessNanos() { + return this.expireAfterAccessNanos == -1L ? 0L : this.expireAfterAccessNanos; + } + + @Beta + @GwtIncompatible(value="To be supported (synchronously).") + public CacheBuilder refreshAfterWrite(long duration, TimeUnit unit) { + Preconditions.checkNotNull(unit); + Preconditions.checkState(this.refreshNanos == -1L, "refresh was already set to %s ns", this.refreshNanos); + Preconditions.checkArgument(duration > 0L, "duration must be positive: %s %s", new Object[]{duration, unit}); + this.refreshNanos = unit.toNanos(duration); + return this; + } + + long getRefreshNanos() { + return this.refreshNanos == -1L ? 0L : this.refreshNanos; + } + + public CacheBuilder ticker(Ticker ticker) { + Preconditions.checkState(this.ticker == null); + this.ticker = Preconditions.checkNotNull(ticker); + return this; + } + + Ticker getTicker(boolean recordsTime) { + if (this.ticker != null) { + return this.ticker; + } + return recordsTime ? Ticker.systemTicker() : NULL_TICKER; + } + + @CheckReturnValue + public CacheBuilder removalListener(RemovalListener listener) { + Preconditions.checkState(this.removalListener == null); + CacheBuilder me = this; + me.removalListener = Preconditions.checkNotNull(listener); + return me; + } + + RemovalListener getRemovalListener() { + return MoreObjects.firstNonNull(this.removalListener, NullListener.INSTANCE); + } + + public CacheBuilder recordStats() { + this.statsCounterSupplier = CACHE_STATS_COUNTER; + return this; + } + + boolean isRecordingStats() { + return this.statsCounterSupplier == CACHE_STATS_COUNTER; + } + + Supplier getStatsCounterSupplier() { + return this.statsCounterSupplier; + } + + public LoadingCache build(CacheLoader loader) { + this.checkWeightWithWeigher(); + return new LocalCache.LocalLoadingCache(this, loader); + } + + public Cache build() { + this.checkWeightWithWeigher(); + this.checkNonLoadingCache(); + return new LocalCache.LocalManualCache(this); + } + + private void checkNonLoadingCache() { + Preconditions.checkState(this.refreshNanos == -1L, "refreshAfterWrite requires a LoadingCache"); + } + + private void checkWeightWithWeigher() { + if (this.weigher == null) { + Preconditions.checkState(this.maximumWeight == -1L, "maximumWeight requires weigher"); + } else if (this.strictParsing) { + Preconditions.checkState(this.maximumWeight != -1L, "weigher requires maximumWeight"); + } else if (this.maximumWeight == -1L) { + logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight"); + } + } + + public String toString() { + long l; + MoreObjects.ToStringHelper s = MoreObjects.toStringHelper(this); + if (this.initialCapacity != -1) { + s.add("initialCapacity", this.initialCapacity); + } + if (this.concurrencyLevel != -1) { + s.add("concurrencyLevel", this.concurrencyLevel); + } + if (this.maximumSize != -1L) { + s.add("maximumSize", this.maximumSize); + } + if (this.maximumWeight != -1L) { + s.add("maximumWeight", this.maximumWeight); + } + if (this.expireAfterWriteNanos != -1L) { + l = this.expireAfterWriteNanos; + s.add("expireAfterWrite", new StringBuilder(22).append(l).append("ns").toString()); + } + if (this.expireAfterAccessNanos != -1L) { + l = this.expireAfterAccessNanos; + s.add("expireAfterAccess", new StringBuilder(22).append(l).append("ns").toString()); + } + if (this.keyStrength != null) { + s.add("keyStrength", Ascii.toLowerCase(this.keyStrength.toString())); + } + if (this.valueStrength != null) { + s.add("valueStrength", Ascii.toLowerCase(this.valueStrength.toString())); + } + if (this.keyEquivalence != null) { + s.addValue("keyEquivalence"); + } + if (this.valueEquivalence != null) { + s.addValue("valueEquivalence"); + } + if (this.removalListener != null) { + s.addValue("removalListener"); + } + return s.toString(); + } + + static enum OneWeigher implements Weigher + { + INSTANCE; + + + @Override + public int weigh(Object key, Object value) { + return 1; + } + } + + static enum NullListener implements RemovalListener + { + INSTANCE; + + + @Override + public void onRemoval(RemovalNotification notification) { + } + } +} diff --git a/src/com/google/common/cache/CacheBuilderSpec.java b/src/com/google/common/cache/CacheBuilderSpec.java new file mode 100644 index 0000000..f0bb88a --- /dev/null +++ b/src/com/google/common/cache/CacheBuilderSpec.java @@ -0,0 +1,378 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.LocalCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +@Beta +public final class CacheBuilderSpec { + private static final Splitter KEYS_SPLITTER = Splitter.on(',').trimResults(); + private static final Splitter KEY_VALUE_SPLITTER = Splitter.on('=').trimResults(); + private static final ImmutableMap VALUE_PARSERS = ImmutableMap.builder().put("initialCapacity", new InitialCapacityParser()).put("maximumSize", (InitialCapacityParser)((Object)new MaximumSizeParser())).put("maximumWeight", (InitialCapacityParser)((Object)new MaximumWeightParser())).put("concurrencyLevel", (InitialCapacityParser)((Object)new ConcurrencyLevelParser())).put("weakKeys", (InitialCapacityParser)((Object)new KeyStrengthParser(LocalCache.Strength.WEAK))).put("softValues", (InitialCapacityParser)((Object)new ValueStrengthParser(LocalCache.Strength.SOFT))).put("weakValues", (InitialCapacityParser)((Object)new ValueStrengthParser(LocalCache.Strength.WEAK))).put("recordStats", (InitialCapacityParser)((Object)new RecordStatsParser())).put("expireAfterAccess", (InitialCapacityParser)((Object)new AccessDurationParser())).put("expireAfterWrite", (InitialCapacityParser)((Object)new WriteDurationParser())).put("refreshAfterWrite", (InitialCapacityParser)((Object)new RefreshDurationParser())).put("refreshInterval", (InitialCapacityParser)((Object)new RefreshDurationParser())).build(); + @VisibleForTesting + Integer initialCapacity; + @VisibleForTesting + Long maximumSize; + @VisibleForTesting + Long maximumWeight; + @VisibleForTesting + Integer concurrencyLevel; + @VisibleForTesting + LocalCache.Strength keyStrength; + @VisibleForTesting + LocalCache.Strength valueStrength; + @VisibleForTesting + Boolean recordStats; + @VisibleForTesting + long writeExpirationDuration; + @VisibleForTesting + TimeUnit writeExpirationTimeUnit; + @VisibleForTesting + long accessExpirationDuration; + @VisibleForTesting + TimeUnit accessExpirationTimeUnit; + @VisibleForTesting + long refreshDuration; + @VisibleForTesting + TimeUnit refreshTimeUnit; + private final String specification; + + private CacheBuilderSpec(String specification) { + this.specification = specification; + } + + public static CacheBuilderSpec parse(String cacheBuilderSpecification) { + CacheBuilderSpec spec = new CacheBuilderSpec(cacheBuilderSpecification); + if (!cacheBuilderSpecification.isEmpty()) { + for (String keyValuePair : KEYS_SPLITTER.split(cacheBuilderSpecification)) { + ImmutableList keyAndValue = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyValuePair)); + Preconditions.checkArgument(!keyAndValue.isEmpty(), "blank key-value pair"); + Preconditions.checkArgument(keyAndValue.size() <= 2, "key-value pair %s with more than one equals sign", keyValuePair); + String key = (String)keyAndValue.get(0); + ValueParser valueParser = VALUE_PARSERS.get(key); + Preconditions.checkArgument(valueParser != null, "unknown key %s", key); + String value = keyAndValue.size() == 1 ? null : (String)keyAndValue.get(1); + valueParser.parse(spec, key, value); + } + } + return spec; + } + + public static CacheBuilderSpec disableCaching() { + return CacheBuilderSpec.parse("maximumSize=0"); + } + + CacheBuilder toCacheBuilder() { + CacheBuilder builder = CacheBuilder.newBuilder(); + if (this.initialCapacity != null) { + builder.initialCapacity(this.initialCapacity); + } + if (this.maximumSize != null) { + builder.maximumSize(this.maximumSize); + } + if (this.maximumWeight != null) { + builder.maximumWeight(this.maximumWeight); + } + if (this.concurrencyLevel != null) { + builder.concurrencyLevel(this.concurrencyLevel); + } + if (this.keyStrength != null) { + switch (this.keyStrength) { + case WEAK: { + builder.weakKeys(); + break; + } + default: { + throw new AssertionError(); + } + } + } + if (this.valueStrength != null) { + switch (this.valueStrength) { + case SOFT: { + builder.softValues(); + break; + } + case WEAK: { + builder.weakValues(); + break; + } + default: { + throw new AssertionError(); + } + } + } + if (this.recordStats != null && this.recordStats.booleanValue()) { + builder.recordStats(); + } + if (this.writeExpirationTimeUnit != null) { + builder.expireAfterWrite(this.writeExpirationDuration, this.writeExpirationTimeUnit); + } + if (this.accessExpirationTimeUnit != null) { + builder.expireAfterAccess(this.accessExpirationDuration, this.accessExpirationTimeUnit); + } + if (this.refreshTimeUnit != null) { + builder.refreshAfterWrite(this.refreshDuration, this.refreshTimeUnit); + } + return builder; + } + + public String toParsableString() { + return this.specification; + } + + public String toString() { + return MoreObjects.toStringHelper(this).addValue(this.toParsableString()).toString(); + } + + public int hashCode() { + return Objects.hashCode(new Object[]{this.initialCapacity, this.maximumSize, this.maximumWeight, this.concurrencyLevel, this.keyStrength, this.valueStrength, this.recordStats, CacheBuilderSpec.durationInNanos(this.writeExpirationDuration, this.writeExpirationTimeUnit), CacheBuilderSpec.durationInNanos(this.accessExpirationDuration, this.accessExpirationTimeUnit), CacheBuilderSpec.durationInNanos(this.refreshDuration, this.refreshTimeUnit)}); + } + + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof CacheBuilderSpec)) { + return false; + } + CacheBuilderSpec that = (CacheBuilderSpec)obj; + return Objects.equal(this.initialCapacity, that.initialCapacity) && Objects.equal(this.maximumSize, that.maximumSize) && Objects.equal(this.maximumWeight, that.maximumWeight) && Objects.equal(this.concurrencyLevel, that.concurrencyLevel) && Objects.equal((Object)this.keyStrength, (Object)that.keyStrength) && Objects.equal((Object)this.valueStrength, (Object)that.valueStrength) && Objects.equal(this.recordStats, that.recordStats) && Objects.equal(CacheBuilderSpec.durationInNanos(this.writeExpirationDuration, this.writeExpirationTimeUnit), CacheBuilderSpec.durationInNanos(that.writeExpirationDuration, that.writeExpirationTimeUnit)) && Objects.equal(CacheBuilderSpec.durationInNanos(this.accessExpirationDuration, this.accessExpirationTimeUnit), CacheBuilderSpec.durationInNanos(that.accessExpirationDuration, that.accessExpirationTimeUnit)) && Objects.equal(CacheBuilderSpec.durationInNanos(this.refreshDuration, this.refreshTimeUnit), CacheBuilderSpec.durationInNanos(that.refreshDuration, that.refreshTimeUnit)); + } + + @Nullable + private static Long durationInNanos(long duration, @Nullable TimeUnit unit) { + return unit == null ? null : Long.valueOf(unit.toNanos(duration)); + } + + static class RefreshDurationParser + extends DurationParser { + RefreshDurationParser() { + } + + @Override + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { + Preconditions.checkArgument(spec.refreshTimeUnit == null, "refreshAfterWrite already set"); + spec.refreshDuration = duration; + spec.refreshTimeUnit = unit; + } + } + + static class WriteDurationParser + extends DurationParser { + WriteDurationParser() { + } + + @Override + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { + Preconditions.checkArgument(spec.writeExpirationTimeUnit == null, "expireAfterWrite already set"); + spec.writeExpirationDuration = duration; + spec.writeExpirationTimeUnit = unit; + } + } + + static class AccessDurationParser + extends DurationParser { + AccessDurationParser() { + } + + @Override + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { + Preconditions.checkArgument(spec.accessExpirationTimeUnit == null, "expireAfterAccess already set"); + spec.accessExpirationDuration = duration; + spec.accessExpirationTimeUnit = unit; + } + } + + static abstract class DurationParser + implements ValueParser { + DurationParser() { + } + + protected abstract void parseDuration(CacheBuilderSpec var1, long var2, TimeUnit var4); + + @Override + public void parse(CacheBuilderSpec spec, String key, String value) { + Preconditions.checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key); + try { + TimeUnit timeUnit; + char lastChar = value.charAt(value.length() - 1); + switch (lastChar) { + case 'd': { + timeUnit = TimeUnit.DAYS; + break; + } + case 'h': { + timeUnit = TimeUnit.HOURS; + break; + } + case 'm': { + timeUnit = TimeUnit.MINUTES; + break; + } + case 's': { + timeUnit = TimeUnit.SECONDS; + break; + } + default: { + throw new IllegalArgumentException(String.format("key %s invalid format. was %s, must end with one of [dDhHmMsS]", key, value)); + } + } + long duration = Long.parseLong(value.substring(0, value.length() - 1)); + this.parseDuration(spec, duration, timeUnit); + } + catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value)); + } + } + } + + static class RecordStatsParser + implements ValueParser { + RecordStatsParser() { + } + + @Override + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) { + Preconditions.checkArgument(value == null, "recordStats does not take values"); + Preconditions.checkArgument(spec.recordStats == null, "recordStats already set"); + spec.recordStats = true; + } + } + + static class ValueStrengthParser + implements ValueParser { + private final LocalCache.Strength strength; + + public ValueStrengthParser(LocalCache.Strength strength) { + this.strength = strength; + } + + @Override + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) { + Preconditions.checkArgument(value == null, "key %s does not take values", key); + Preconditions.checkArgument(spec.valueStrength == null, "%s was already set to %s", new Object[]{key, spec.valueStrength}); + spec.valueStrength = this.strength; + } + } + + static class KeyStrengthParser + implements ValueParser { + private final LocalCache.Strength strength; + + public KeyStrengthParser(LocalCache.Strength strength) { + this.strength = strength; + } + + @Override + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) { + Preconditions.checkArgument(value == null, "key %s does not take values", key); + Preconditions.checkArgument(spec.keyStrength == null, "%s was already set to %s", new Object[]{key, spec.keyStrength}); + spec.keyStrength = this.strength; + } + } + + static class ConcurrencyLevelParser + extends IntegerParser { + ConcurrencyLevelParser() { + } + + @Override + protected void parseInteger(CacheBuilderSpec spec, int value) { + Preconditions.checkArgument(spec.concurrencyLevel == null, "concurrency level was already set to ", spec.concurrencyLevel); + spec.concurrencyLevel = value; + } + } + + static class MaximumWeightParser + extends LongParser { + MaximumWeightParser() { + } + + @Override + protected void parseLong(CacheBuilderSpec spec, long value) { + Preconditions.checkArgument(spec.maximumWeight == null, "maximum weight was already set to ", spec.maximumWeight); + Preconditions.checkArgument(spec.maximumSize == null, "maximum size was already set to ", spec.maximumSize); + spec.maximumWeight = value; + } + } + + static class MaximumSizeParser + extends LongParser { + MaximumSizeParser() { + } + + @Override + protected void parseLong(CacheBuilderSpec spec, long value) { + Preconditions.checkArgument(spec.maximumSize == null, "maximum size was already set to ", spec.maximumSize); + Preconditions.checkArgument(spec.maximumWeight == null, "maximum weight was already set to ", spec.maximumWeight); + spec.maximumSize = value; + } + } + + static class InitialCapacityParser + extends IntegerParser { + InitialCapacityParser() { + } + + @Override + protected void parseInteger(CacheBuilderSpec spec, int value) { + Preconditions.checkArgument(spec.initialCapacity == null, "initial capacity was already set to ", spec.initialCapacity); + spec.initialCapacity = value; + } + } + + static abstract class LongParser + implements ValueParser { + LongParser() { + } + + protected abstract void parseLong(CacheBuilderSpec var1, long var2); + + @Override + public void parse(CacheBuilderSpec spec, String key, String value) { + Preconditions.checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key); + try { + this.parseLong(spec, Long.parseLong(value)); + } + catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value), e); + } + } + } + + static abstract class IntegerParser + implements ValueParser { + IntegerParser() { + } + + protected abstract void parseInteger(CacheBuilderSpec var1, int var2); + + @Override + public void parse(CacheBuilderSpec spec, String key, String value) { + Preconditions.checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key); + try { + this.parseInteger(spec, Integer.parseInt(value)); + } + catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", key, value), e); + } + } + } + + private static interface ValueParser { + public void parse(CacheBuilderSpec var1, String var2, @Nullable String var3); + } +} diff --git a/src/com/google/common/cache/CacheLoader.java b/src/com/google/common/cache/CacheLoader.java new file mode 100644 index 0000000..967e118 --- /dev/null +++ b/src/com/google/common/cache/CacheLoader.java @@ -0,0 +1,125 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; + +@GwtCompatible(emulated=true) +public abstract class CacheLoader { + protected CacheLoader() { + } + + public abstract V load(K var1) throws Exception; + + @GwtIncompatible(value="Futures") + public ListenableFuture reload(K key, V oldValue) throws Exception { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(oldValue); + return Futures.immediateFuture(this.load(key)); + } + + public Map loadAll(Iterable keys) throws Exception { + throw new UnsupportedLoadingOperationException(); + } + + @Beta + public static CacheLoader from(Function function) { + return new FunctionToCacheLoader(function); + } + + @Beta + public static CacheLoader from(Supplier supplier) { + return new SupplierToCacheLoader(supplier); + } + + @Beta + @GwtIncompatible(value="Executor + Futures") + public static CacheLoader asyncReloading(final CacheLoader loader, final Executor executor) { + Preconditions.checkNotNull(loader); + Preconditions.checkNotNull(executor); + return new CacheLoader(){ + + @Override + public V load(K key) throws Exception { + return loader.load(key); + } + + @Override + public ListenableFuture reload(final K key, final V oldValue) throws Exception { + ListenableFutureTask task = ListenableFutureTask.create(new Callable(){ + + @Override + public V call() throws Exception { + return loader.reload(key, oldValue).get(); + } + }); + executor.execute(task); + return task; + } + + @Override + public Map loadAll(Iterable keys) throws Exception { + return loader.loadAll(keys); + } + }; + } + + public static final class InvalidCacheLoadException + extends RuntimeException { + public InvalidCacheLoadException(String message) { + super(message); + } + } + + static final class UnsupportedLoadingOperationException + extends UnsupportedOperationException { + UnsupportedLoadingOperationException() { + } + } + + private static final class SupplierToCacheLoader + extends CacheLoader + implements Serializable { + private final Supplier computingSupplier; + private static final long serialVersionUID = 0L; + + public SupplierToCacheLoader(Supplier computingSupplier) { + this.computingSupplier = Preconditions.checkNotNull(computingSupplier); + } + + @Override + public V load(Object key) { + Preconditions.checkNotNull(key); + return this.computingSupplier.get(); + } + } + + private static final class FunctionToCacheLoader + extends CacheLoader + implements Serializable { + private final Function computingFunction; + private static final long serialVersionUID = 0L; + + public FunctionToCacheLoader(Function computingFunction) { + this.computingFunction = Preconditions.checkNotNull(computingFunction); + } + + @Override + public V load(K key) { + return this.computingFunction.apply(Preconditions.checkNotNull(key)); + } + } +} diff --git a/src/com/google/common/cache/CacheStats.java b/src/com/google/common/cache/CacheStats.java new file mode 100644 index 0000000..a2883a7 --- /dev/null +++ b/src/com/google/common/cache/CacheStats.java @@ -0,0 +1,113 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class CacheStats { + private final long hitCount; + private final long missCount; + private final long loadSuccessCount; + private final long loadExceptionCount; + private final long totalLoadTime; + private final long evictionCount; + + public CacheStats(long hitCount, long missCount, long loadSuccessCount, long loadExceptionCount, long totalLoadTime, long evictionCount) { + Preconditions.checkArgument(hitCount >= 0L); + Preconditions.checkArgument(missCount >= 0L); + Preconditions.checkArgument(loadSuccessCount >= 0L); + Preconditions.checkArgument(loadExceptionCount >= 0L); + Preconditions.checkArgument(totalLoadTime >= 0L); + Preconditions.checkArgument(evictionCount >= 0L); + this.hitCount = hitCount; + this.missCount = missCount; + this.loadSuccessCount = loadSuccessCount; + this.loadExceptionCount = loadExceptionCount; + this.totalLoadTime = totalLoadTime; + this.evictionCount = evictionCount; + } + + public long requestCount() { + return this.hitCount + this.missCount; + } + + public long hitCount() { + return this.hitCount; + } + + public double hitRate() { + long requestCount = this.requestCount(); + return requestCount == 0L ? 1.0 : (double)this.hitCount / (double)requestCount; + } + + public long missCount() { + return this.missCount; + } + + public double missRate() { + long requestCount = this.requestCount(); + return requestCount == 0L ? 0.0 : (double)this.missCount / (double)requestCount; + } + + public long loadCount() { + return this.loadSuccessCount + this.loadExceptionCount; + } + + public long loadSuccessCount() { + return this.loadSuccessCount; + } + + public long loadExceptionCount() { + return this.loadExceptionCount; + } + + public double loadExceptionRate() { + long totalLoadCount = this.loadSuccessCount + this.loadExceptionCount; + return totalLoadCount == 0L ? 0.0 : (double)this.loadExceptionCount / (double)totalLoadCount; + } + + public long totalLoadTime() { + return this.totalLoadTime; + } + + public double averageLoadPenalty() { + long totalLoadCount = this.loadSuccessCount + this.loadExceptionCount; + return totalLoadCount == 0L ? 0.0 : (double)this.totalLoadTime / (double)totalLoadCount; + } + + public long evictionCount() { + return this.evictionCount; + } + + public CacheStats minus(CacheStats other) { + return new CacheStats(Math.max(0L, this.hitCount - other.hitCount), Math.max(0L, this.missCount - other.missCount), Math.max(0L, this.loadSuccessCount - other.loadSuccessCount), Math.max(0L, this.loadExceptionCount - other.loadExceptionCount), Math.max(0L, this.totalLoadTime - other.totalLoadTime), Math.max(0L, this.evictionCount - other.evictionCount)); + } + + public CacheStats plus(CacheStats other) { + return new CacheStats(this.hitCount + other.hitCount, this.missCount + other.missCount, this.loadSuccessCount + other.loadSuccessCount, this.loadExceptionCount + other.loadExceptionCount, this.totalLoadTime + other.totalLoadTime, this.evictionCount + other.evictionCount); + } + + public int hashCode() { + return Objects.hashCode(this.hitCount, this.missCount, this.loadSuccessCount, this.loadExceptionCount, this.totalLoadTime, this.evictionCount); + } + + public boolean equals(@Nullable Object object) { + if (object instanceof CacheStats) { + CacheStats other = (CacheStats)object; + return this.hitCount == other.hitCount && this.missCount == other.missCount && this.loadSuccessCount == other.loadSuccessCount && this.loadExceptionCount == other.loadExceptionCount && this.totalLoadTime == other.totalLoadTime && this.evictionCount == other.evictionCount; + } + return false; + } + + public String toString() { + return MoreObjects.toStringHelper(this).add("hitCount", this.hitCount).add("missCount", this.missCount).add("loadSuccessCount", this.loadSuccessCount).add("loadExceptionCount", this.loadExceptionCount).add("totalLoadTime", this.totalLoadTime).add("evictionCount", this.evictionCount).toString(); + } +} diff --git a/src/com/google/common/cache/ForwardingCache.java b/src/com/google/common/cache/ForwardingCache.java new file mode 100644 index 0000000..053e3af --- /dev/null +++ b/src/com/google/common/cache/ForwardingCache.java @@ -0,0 +1,103 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import javax.annotation.Nullable; + +@Beta +public abstract class ForwardingCache +extends ForwardingObject +implements Cache { + protected ForwardingCache() { + } + + @Override + protected abstract Cache delegate(); + + @Override + @Nullable + public V getIfPresent(Object key) { + return this.delegate().getIfPresent(key); + } + + @Override + public V get(K key, Callable valueLoader) throws ExecutionException { + return this.delegate().get(key, valueLoader); + } + + @Override + public ImmutableMap getAllPresent(Iterable keys) { + return this.delegate().getAllPresent(keys); + } + + @Override + public void put(K key, V value) { + this.delegate().put(key, value); + } + + @Override + public void putAll(Map m) { + this.delegate().putAll(m); + } + + @Override + public void invalidate(Object key) { + this.delegate().invalidate(key); + } + + @Override + public void invalidateAll(Iterable keys) { + this.delegate().invalidateAll(keys); + } + + @Override + public void invalidateAll() { + this.delegate().invalidateAll(); + } + + @Override + public long size() { + return this.delegate().size(); + } + + @Override + public CacheStats stats() { + return this.delegate().stats(); + } + + @Override + public ConcurrentMap asMap() { + return this.delegate().asMap(); + } + + @Override + public void cleanUp() { + this.delegate().cleanUp(); + } + + @Beta + public static abstract class SimpleForwardingCache + extends ForwardingCache { + private final Cache delegate; + + protected SimpleForwardingCache(Cache delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected final Cache delegate() { + return this.delegate; + } + } +} diff --git a/src/com/google/common/cache/ForwardingLoadingCache.java b/src/com/google/common/cache/ForwardingLoadingCache.java new file mode 100644 index 0000000..b9cca2e --- /dev/null +++ b/src/com/google/common/cache/ForwardingLoadingCache.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.ForwardingCache; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.ExecutionException; + +@Beta +public abstract class ForwardingLoadingCache +extends ForwardingCache +implements LoadingCache { + protected ForwardingLoadingCache() { + } + + @Override + protected abstract LoadingCache delegate(); + + @Override + public V get(K key) throws ExecutionException { + return this.delegate().get(key); + } + + @Override + public V getUnchecked(K key) { + return this.delegate().getUnchecked(key); + } + + @Override + public ImmutableMap getAll(Iterable keys) throws ExecutionException { + return this.delegate().getAll(keys); + } + + @Override + public V apply(K key) { + return this.delegate().apply(key); + } + + @Override + public void refresh(K key) { + this.delegate().refresh(key); + } + + @Beta + public static abstract class SimpleForwardingLoadingCache + extends ForwardingLoadingCache { + private final LoadingCache delegate; + + protected SimpleForwardingLoadingCache(LoadingCache delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected final LoadingCache delegate() { + return this.delegate; + } + } +} diff --git a/src/com/google/common/cache/LoadingCache.java b/src/com/google/common/cache/LoadingCache.java new file mode 100644 index 0000000..285c63a --- /dev/null +++ b/src/com/google/common/cache/LoadingCache.java @@ -0,0 +1,33 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.cache.Cache; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + +@Beta +@GwtCompatible +public interface LoadingCache +extends Cache, +Function { + public V get(K var1) throws ExecutionException; + + public V getUnchecked(K var1); + + public ImmutableMap getAll(Iterable var1) throws ExecutionException; + + @Override + @Deprecated + public V apply(K var1); + + public void refresh(K var1); + + @Override + public ConcurrentMap asMap(); +} diff --git a/src/com/google/common/cache/LocalCache.java b/src/com/google/common/cache/LocalCache.java new file mode 100644 index 0000000..c2a6ce6 --- /dev/null +++ b/src/com/google/common/cache/LocalCache.java @@ -0,0 +1,3939 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; +import com.google.common.base.Ticker; +import com.google.common.cache.AbstractCache; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.CacheStats; +import com.google.common.cache.ForwardingCache; +import com.google.common.cache.LoadingCache; +import com.google.common.cache.RemovalCause; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; +import com.google.common.cache.Weigher; +import com.google.common.collect.AbstractSequentialIterator; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.ExecutionError; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SettableFuture; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.common.util.concurrent.Uninterruptibles; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractQueue; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + +@GwtCompatible(emulated=true) +class LocalCache +extends AbstractMap +implements ConcurrentMap { + static final int MAXIMUM_CAPACITY = 0x40000000; + static final int MAX_SEGMENTS = 65536; + static final int CONTAINS_VALUE_RETRIES = 3; + static final int DRAIN_THRESHOLD = 63; + static final int DRAIN_MAX = 16; + static final Logger logger = Logger.getLogger(LocalCache.class.getName()); + final int segmentMask; + final int segmentShift; + final Segment[] segments; + final int concurrencyLevel; + final Equivalence keyEquivalence; + final Equivalence valueEquivalence; + final Strength keyStrength; + final Strength valueStrength; + final long maxWeight; + final Weigher weigher; + final long expireAfterAccessNanos; + final long expireAfterWriteNanos; + final long refreshNanos; + final Queue> removalNotificationQueue; + final RemovalListener removalListener; + final Ticker ticker; + final EntryFactory entryFactory; + final AbstractCache.StatsCounter globalStatsCounter; + @Nullable + final CacheLoader defaultLoader; + static final ValueReference UNSET = new ValueReference(){ + + @Override + public Object get() { + return null; + } + + @Override + public int getWeight() { + return 0; + } + + @Override + public ReferenceEntry getEntry() { + return null; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, @Nullable Object value, ReferenceEntry entry) { + return this; + } + + @Override + public boolean isLoading() { + return false; + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public Object waitForValue() { + return null; + } + + @Override + public void notifyNewValue(Object newValue) { + } + }; + static final Queue DISCARDING_QUEUE = new AbstractQueue(){ + + @Override + public boolean offer(Object o) { + return true; + } + + @Override + public Object peek() { + return null; + } + + @Override + public Object poll() { + return null; + } + + @Override + public int size() { + return 0; + } + + @Override + public Iterator iterator() { + return ImmutableSet.of().iterator(); + } + }; + Set keySet; + Collection values; + Set> entrySet; + + LocalCache(CacheBuilder builder, @Nullable CacheLoader loader) { + int segmentSize; + int segmentCount; + this.concurrencyLevel = Math.min(builder.getConcurrencyLevel(), 65536); + this.keyStrength = builder.getKeyStrength(); + this.valueStrength = builder.getValueStrength(); + this.keyEquivalence = builder.getKeyEquivalence(); + this.valueEquivalence = builder.getValueEquivalence(); + this.maxWeight = builder.getMaximumWeight(); + this.weigher = builder.getWeigher(); + this.expireAfterAccessNanos = builder.getExpireAfterAccessNanos(); + this.expireAfterWriteNanos = builder.getExpireAfterWriteNanos(); + this.refreshNanos = builder.getRefreshNanos(); + this.removalListener = builder.getRemovalListener(); + this.removalNotificationQueue = this.removalListener == CacheBuilder.NullListener.INSTANCE ? LocalCache.discardingQueue() : new ConcurrentLinkedQueue(); + this.ticker = builder.getTicker(this.recordsTime()); + this.entryFactory = EntryFactory.getFactory(this.keyStrength, this.usesAccessEntries(), this.usesWriteEntries()); + this.globalStatsCounter = builder.getStatsCounterSupplier().get(); + this.defaultLoader = loader; + int initialCapacity = Math.min(builder.getInitialCapacity(), 0x40000000); + if (this.evictsBySize() && !this.customWeigher()) { + initialCapacity = Math.min(initialCapacity, (int)this.maxWeight); + } + int segmentShift = 0; + for (segmentCount = 1; !(segmentCount >= this.concurrencyLevel || this.evictsBySize() && (long)(segmentCount * 20) > this.maxWeight); segmentCount <<= 1) { + ++segmentShift; + } + this.segmentShift = 32 - segmentShift; + this.segmentMask = segmentCount - 1; + this.segments = this.newSegmentArray(segmentCount); + int segmentCapacity = initialCapacity / segmentCount; + if (segmentCapacity * segmentCount < initialCapacity) { + ++segmentCapacity; + } + for (segmentSize = 1; segmentSize < segmentCapacity; segmentSize <<= 1) { + } + if (this.evictsBySize()) { + long maxSegmentWeight = this.maxWeight / (long)segmentCount + 1L; + long remainder = this.maxWeight % (long)segmentCount; + for (int i = 0; i < this.segments.length; ++i) { + if ((long)i == remainder) { + --maxSegmentWeight; + } + this.segments[i] = this.createSegment(segmentSize, maxSegmentWeight, builder.getStatsCounterSupplier().get()); + } + } else { + for (int i = 0; i < this.segments.length; ++i) { + this.segments[i] = this.createSegment(segmentSize, -1L, builder.getStatsCounterSupplier().get()); + } + } + } + + boolean evictsBySize() { + return this.maxWeight >= 0L; + } + + boolean customWeigher() { + return this.weigher != CacheBuilder.OneWeigher.INSTANCE; + } + + boolean expires() { + return this.expiresAfterWrite() || this.expiresAfterAccess(); + } + + boolean expiresAfterWrite() { + return this.expireAfterWriteNanos > 0L; + } + + boolean expiresAfterAccess() { + return this.expireAfterAccessNanos > 0L; + } + + boolean refreshes() { + return this.refreshNanos > 0L; + } + + boolean usesAccessQueue() { + return this.expiresAfterAccess() || this.evictsBySize(); + } + + boolean usesWriteQueue() { + return this.expiresAfterWrite(); + } + + boolean recordsWrite() { + return this.expiresAfterWrite() || this.refreshes(); + } + + boolean recordsAccess() { + return this.expiresAfterAccess(); + } + + boolean recordsTime() { + return this.recordsWrite() || this.recordsAccess(); + } + + boolean usesWriteEntries() { + return this.usesWriteQueue() || this.recordsWrite(); + } + + boolean usesAccessEntries() { + return this.usesAccessQueue() || this.recordsAccess(); + } + + boolean usesKeyReferences() { + return this.keyStrength != Strength.STRONG; + } + + boolean usesValueReferences() { + return this.valueStrength != Strength.STRONG; + } + + static ValueReference unset() { + return UNSET; + } + + static ReferenceEntry nullEntry() { + return NullEntry.INSTANCE; + } + + static Queue discardingQueue() { + return DISCARDING_QUEUE; + } + + static int rehash(int h) { + h += h << 15 ^ 0xFFFFCD7D; + h ^= h >>> 10; + h += h << 3; + h ^= h >>> 6; + h += (h << 2) + (h << 14); + return h ^ h >>> 16; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @VisibleForTesting + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) { + Segment segment = this.segmentFor(hash); + segment.lock(); + try { + ReferenceEntry referenceEntry = segment.newEntry(key, hash, next); + return referenceEntry; + } + finally { + segment.unlock(); + } + } + + @VisibleForTesting + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) { + int hash = original.getHash(); + return this.segmentFor(hash).copyEntry(original, newNext); + } + + @VisibleForTesting + ValueReference newValueReference(ReferenceEntry entry, V value, int weight) { + int hash = entry.getHash(); + return this.valueStrength.referenceValue(this.segmentFor(hash), entry, Preconditions.checkNotNull(value), weight); + } + + int hash(@Nullable Object key) { + int h = this.keyEquivalence.hash(key); + return LocalCache.rehash(h); + } + + void reclaimValue(ValueReference valueReference) { + ReferenceEntry entry = valueReference.getEntry(); + int hash = entry.getHash(); + this.segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); + } + + void reclaimKey(ReferenceEntry entry) { + int hash = entry.getHash(); + this.segmentFor(hash).reclaimKey(entry, hash); + } + + @VisibleForTesting + boolean isLive(ReferenceEntry entry, long now) { + return this.segmentFor(entry.getHash()).getLiveValue(entry, now) != null; + } + + Segment segmentFor(int hash) { + return this.segments[hash >>> this.segmentShift & this.segmentMask]; + } + + Segment createSegment(int initialCapacity, long maxSegmentWeight, AbstractCache.StatsCounter statsCounter) { + return new Segment(this, initialCapacity, maxSegmentWeight, statsCounter); + } + + @Nullable + V getLiveValue(ReferenceEntry entry, long now) { + if (entry.getKey() == null) { + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + return null; + } + if (this.isExpired(entry, now)) { + return null; + } + return value; + } + + boolean isExpired(ReferenceEntry entry, long now) { + Preconditions.checkNotNull(entry); + if (this.expiresAfterAccess() && now - entry.getAccessTime() >= this.expireAfterAccessNanos) { + return true; + } + return this.expiresAfterWrite() && now - entry.getWriteTime() >= this.expireAfterWriteNanos; + } + + static void connectAccessOrder(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextInAccessQueue(next); + next.setPreviousInAccessQueue(previous); + } + + static void nullifyAccessOrder(ReferenceEntry nulled) { + ReferenceEntry nullEntry = LocalCache.nullEntry(); + nulled.setNextInAccessQueue(nullEntry); + nulled.setPreviousInAccessQueue(nullEntry); + } + + static void connectWriteOrder(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextInWriteQueue(next); + next.setPreviousInWriteQueue(previous); + } + + static void nullifyWriteOrder(ReferenceEntry nulled) { + ReferenceEntry nullEntry = LocalCache.nullEntry(); + nulled.setNextInWriteQueue(nullEntry); + nulled.setPreviousInWriteQueue(nullEntry); + } + + void processPendingNotifications() { + RemovalNotification notification; + while ((notification = this.removalNotificationQueue.poll()) != null) { + try { + this.removalListener.onRemoval(notification); + } + catch (Throwable e) { + logger.log(Level.WARNING, "Exception thrown by removal listener", e); + } + } + } + + final Segment[] newSegmentArray(int ssize) { + return new Segment[ssize]; + } + + public void cleanUp() { + for (Segment segment : this.segments) { + segment.cleanUp(); + } + } + + @Override + public boolean isEmpty() { + int i; + long sum = 0L; + Segment[] segments = this.segments; + for (i = 0; i < segments.length; ++i) { + if (segments[i].count != 0) { + return false; + } + sum += (long)segments[i].modCount; + } + if (sum != 0L) { + for (i = 0; i < segments.length; ++i) { + if (segments[i].count != 0) { + return false; + } + sum -= (long)segments[i].modCount; + } + if (sum != 0L) { + return false; + } + } + return true; + } + + long longSize() { + Segment[] segments = this.segments; + long sum = 0L; + for (int i = 0; i < segments.length; ++i) { + sum += (long)segments[i].count; + } + return sum; + } + + @Override + public int size() { + return Ints.saturatedCast(this.longSize()); + } + + @Override + @Nullable + public V get(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).get(key, hash); + } + + @Nullable + public V getIfPresent(Object key) { + int hash = this.hash(Preconditions.checkNotNull(key)); + V value = this.segmentFor(hash).get(key, hash); + if (value == null) { + this.globalStatsCounter.recordMisses(1); + } else { + this.globalStatsCounter.recordHits(1); + } + return value; + } + + V get(K key, CacheLoader loader) throws ExecutionException { + int hash = this.hash(Preconditions.checkNotNull(key)); + return this.segmentFor(hash).get((K)key, hash, loader); + } + + V getOrLoad(K key) throws ExecutionException { + return this.get(key, this.defaultLoader); + } + + ImmutableMap getAllPresent(Iterable keys) { + int hits = 0; + int misses = 0; + LinkedHashMap result = Maps.newLinkedHashMap(); + for (Object key : keys) { + V value = this.get(key); + if (value == null) { + ++misses; + continue; + } + Object castKey = key; + result.put(castKey, value); + ++hits; + } + this.globalStatsCounter.recordHits(hits); + this.globalStatsCounter.recordMisses(misses); + return ImmutableMap.copyOf(result); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + ImmutableMap getAll(Iterable keys) throws ExecutionException { + int hits = 0; + int misses = 0; + LinkedHashMap result = Maps.newLinkedHashMap(); + LinkedHashSet keysToLoad = Sets.newLinkedHashSet(); + for (K key : keys) { + V value = this.get(key); + if (result.containsKey(key)) continue; + result.put(key, value); + if (value == null) { + ++misses; + keysToLoad.add(key); + continue; + } + ++hits; + } + try { + if (!keysToLoad.isEmpty()) { + try { + Map newEntries = this.loadAll(keysToLoad, this.defaultLoader); + for (Object key : keysToLoad) { + V value = newEntries.get(key); + if (value == null) { + String string = String.valueOf(String.valueOf(key)); + throw new CacheLoader.InvalidCacheLoadException(new StringBuilder(37 + string.length()).append("loadAll failed to return a value for ").append(string).toString()); + } + result.put(key, value); + } + } + catch (CacheLoader.UnsupportedLoadingOperationException e) { + for (Object key : keysToLoad) { + --misses; + result.put(key, this.get(key, this.defaultLoader)); + } + } + } + ImmutableMap immutableMap = ImmutableMap.copyOf(result); + return immutableMap; + } + finally { + this.globalStatsCounter.recordHits(hits); + this.globalStatsCounter.recordMisses(misses); + } + } + + @Nullable + Map loadAll(Set keys, CacheLoader loader) throws ExecutionException { + Map result; + Preconditions.checkNotNull(loader); + Preconditions.checkNotNull(keys); + Stopwatch stopwatch = Stopwatch.createStarted(); + boolean success = false; + try { + Map map; + result = map = loader.loadAll(keys); + success = true; + } + catch (CacheLoader.UnsupportedLoadingOperationException e) { + success = true; + throw e; + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ExecutionException(e); + } + catch (RuntimeException e) { + throw new UncheckedExecutionException(e); + } + catch (Exception e) { + throw new ExecutionException(e); + } + catch (Error e) { + throw new ExecutionError(e); + } + finally { + if (!success) { + this.globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + } + } + if (result == null) { + this.globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + String e = String.valueOf(String.valueOf(loader)); + throw new CacheLoader.InvalidCacheLoadException(new StringBuilder(31 + e.length()).append(e).append(" returned null map from loadAll").toString()); + } + stopwatch.stop(); + boolean nullsPresent = false; + for (Map.Entry entry : result.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if (key == null || value == null) { + nullsPresent = true; + continue; + } + this.put(key, value); + } + if (nullsPresent) { + this.globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + String string = String.valueOf(String.valueOf(loader)); + throw new CacheLoader.InvalidCacheLoadException(new StringBuilder(42 + string.length()).append(string).append(" returned null keys or values from loadAll").toString()); + } + this.globalStatsCounter.recordLoadSuccess(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + return result; + } + + ReferenceEntry getEntry(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).getEntry(key, hash); + } + + void refresh(K key) { + int hash = this.hash(Preconditions.checkNotNull(key)); + this.segmentFor(hash).refresh((K)key, hash, this.defaultLoader, false); + } + + @Override + public boolean containsKey(@Nullable Object key) { + if (key == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).containsKey(key, hash); + } + + @Override + public boolean containsValue(@Nullable Object value) { + if (value == null) { + return false; + } + long now = this.ticker.read(); + Segment[] segments = this.segments; + long last = -1L; + for (int i = 0; i < 3; ++i) { + long sum = 0L; + for (Segment segment : segments) { + int c = segment.count; + AtomicReferenceArray table = segment.table; + for (int j = 0; j < table.length(); ++j) { + for (ReferenceEntry e = table.get(j); e != null; e = e.getNext()) { + V v = segment.getLiveValue(e, now); + if (v == null || !this.valueEquivalence.equivalent(value, v)) continue; + return true; + } + } + sum += (long)segment.modCount; + } + if (sum == last) break; + last = sum; + } + return false; + } + + @Override + public V put(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).put(key, hash, value, false); + } + + @Override + public V putIfAbsent(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).put(key, hash, value, true); + } + + @Override + public void putAll(Map m) { + for (Map.Entry e : m.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + @Override + public V remove(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).remove(key, hash); + } + + @Override + public boolean remove(@Nullable Object key, @Nullable Object value) { + if (key == null || value == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).remove(key, hash, value); + } + + @Override + public boolean replace(K key, @Nullable V oldValue, V newValue) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + if (oldValue == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).replace(key, hash, oldValue, newValue); + } + + @Override + public V replace(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).replace(key, hash, value); + } + + @Override + public void clear() { + for (Segment segment : this.segments) { + segment.clear(); + } + } + + void invalidateAll(Iterable keys) { + for (Object key : keys) { + this.remove(key); + } + } + + @Override + public Set keySet() { + KeySet ks = this.keySet; + return ks != null ? ks : (this.keySet = new KeySet(this)); + } + + @Override + public Collection values() { + Values vs = this.values; + return vs != null ? vs : (this.values = new Values(this)); + } + + @Override + @GwtIncompatible(value="Not supported.") + public Set> entrySet() { + EntrySet es = this.entrySet; + return es != null ? es : (this.entrySet = new EntrySet(this)); + } + + static class LocalLoadingCache + extends LocalManualCache + implements LoadingCache { + private static final long serialVersionUID = 1L; + + LocalLoadingCache(CacheBuilder builder, CacheLoader loader) { + super(new LocalCache(builder, Preconditions.checkNotNull(loader))); + } + + @Override + public V get(K key) throws ExecutionException { + return this.localCache.getOrLoad(key); + } + + @Override + public V getUnchecked(K key) { + try { + return this.get(key); + } + catch (ExecutionException e) { + throw new UncheckedExecutionException(e.getCause()); + } + } + + @Override + public ImmutableMap getAll(Iterable keys) throws ExecutionException { + return this.localCache.getAll(keys); + } + + @Override + public void refresh(K key) { + this.localCache.refresh(key); + } + + @Override + public final V apply(K key) { + return this.getUnchecked(key); + } + + @Override + Object writeReplace() { + return new LoadingSerializationProxy(this.localCache); + } + } + + static class LocalManualCache + implements Cache, + Serializable { + final LocalCache localCache; + private static final long serialVersionUID = 1L; + + LocalManualCache(CacheBuilder builder) { + this(new LocalCache(builder, null)); + } + + private LocalManualCache(LocalCache localCache) { + this.localCache = localCache; + } + + @Override + @Nullable + public V getIfPresent(Object key) { + return this.localCache.getIfPresent(key); + } + + @Override + public V get(K key, final Callable valueLoader) throws ExecutionException { + Preconditions.checkNotNull(valueLoader); + return this.localCache.get(key, new CacheLoader(){ + + @Override + public V load(Object key) throws Exception { + return valueLoader.call(); + } + }); + } + + @Override + public ImmutableMap getAllPresent(Iterable keys) { + return this.localCache.getAllPresent(keys); + } + + @Override + public void put(K key, V value) { + this.localCache.put(key, value); + } + + @Override + public void putAll(Map m) { + this.localCache.putAll(m); + } + + @Override + public void invalidate(Object key) { + Preconditions.checkNotNull(key); + this.localCache.remove(key); + } + + @Override + public void invalidateAll(Iterable keys) { + this.localCache.invalidateAll(keys); + } + + @Override + public void invalidateAll() { + this.localCache.clear(); + } + + @Override + public long size() { + return this.localCache.longSize(); + } + + @Override + public ConcurrentMap asMap() { + return this.localCache; + } + + @Override + public CacheStats stats() { + AbstractCache.SimpleStatsCounter aggregator = new AbstractCache.SimpleStatsCounter(); + aggregator.incrementBy(this.localCache.globalStatsCounter); + for (Segment segment : this.localCache.segments) { + aggregator.incrementBy(segment.statsCounter); + } + return aggregator.snapshot(); + } + + @Override + public void cleanUp() { + this.localCache.cleanUp(); + } + + Object writeReplace() { + return new ManualSerializationProxy(this.localCache); + } + } + + static final class LoadingSerializationProxy + extends ManualSerializationProxy + implements LoadingCache, + Serializable { + private static final long serialVersionUID = 1L; + transient LoadingCache autoDelegate; + + LoadingSerializationProxy(LocalCache cache) { + super(cache); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + CacheBuilder builder = this.recreateCacheBuilder(); + this.autoDelegate = builder.build(this.loader); + } + + @Override + public V get(K key) throws ExecutionException { + return this.autoDelegate.get(key); + } + + @Override + public V getUnchecked(K key) { + return this.autoDelegate.getUnchecked(key); + } + + @Override + public ImmutableMap getAll(Iterable keys) throws ExecutionException { + return this.autoDelegate.getAll(keys); + } + + @Override + public final V apply(K key) { + return this.autoDelegate.apply(key); + } + + @Override + public void refresh(K key) { + this.autoDelegate.refresh(key); + } + + private Object readResolve() { + return this.autoDelegate; + } + } + + static class ManualSerializationProxy + extends ForwardingCache + implements Serializable { + private static final long serialVersionUID = 1L; + final Strength keyStrength; + final Strength valueStrength; + final Equivalence keyEquivalence; + final Equivalence valueEquivalence; + final long expireAfterWriteNanos; + final long expireAfterAccessNanos; + final long maxWeight; + final Weigher weigher; + final int concurrencyLevel; + final RemovalListener removalListener; + final Ticker ticker; + final CacheLoader loader; + transient Cache delegate; + + ManualSerializationProxy(LocalCache cache) { + this(cache.keyStrength, cache.valueStrength, cache.keyEquivalence, cache.valueEquivalence, cache.expireAfterWriteNanos, cache.expireAfterAccessNanos, cache.maxWeight, cache.weigher, cache.concurrencyLevel, cache.removalListener, cache.ticker, cache.defaultLoader); + } + + private ManualSerializationProxy(Strength keyStrength, Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, long maxWeight, Weigher weigher, int concurrencyLevel, RemovalListener removalListener, Ticker ticker, CacheLoader loader) { + this.keyStrength = keyStrength; + this.valueStrength = valueStrength; + this.keyEquivalence = keyEquivalence; + this.valueEquivalence = valueEquivalence; + this.expireAfterWriteNanos = expireAfterWriteNanos; + this.expireAfterAccessNanos = expireAfterAccessNanos; + this.maxWeight = maxWeight; + this.weigher = weigher; + this.concurrencyLevel = concurrencyLevel; + this.removalListener = removalListener; + this.ticker = ticker == Ticker.systemTicker() || ticker == CacheBuilder.NULL_TICKER ? null : ticker; + this.loader = loader; + } + + CacheBuilder recreateCacheBuilder() { + CacheBuilder builder = CacheBuilder.newBuilder().setKeyStrength(this.keyStrength).setValueStrength(this.valueStrength).keyEquivalence(this.keyEquivalence).valueEquivalence(this.valueEquivalence).concurrencyLevel(this.concurrencyLevel).removalListener(this.removalListener); + builder.strictParsing = false; + if (this.expireAfterWriteNanos > 0L) { + builder.expireAfterWrite(this.expireAfterWriteNanos, TimeUnit.NANOSECONDS); + } + if (this.expireAfterAccessNanos > 0L) { + builder.expireAfterAccess(this.expireAfterAccessNanos, TimeUnit.NANOSECONDS); + } + if (this.weigher != CacheBuilder.OneWeigher.INSTANCE) { + builder.weigher(this.weigher); + if (this.maxWeight != -1L) { + builder.maximumWeight(this.maxWeight); + } + } else if (this.maxWeight != -1L) { + builder.maximumSize(this.maxWeight); + } + if (this.ticker != null) { + builder.ticker(this.ticker); + } + return builder; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + CacheBuilder builder = this.recreateCacheBuilder(); + this.delegate = builder.build(); + } + + private Object readResolve() { + return this.delegate; + } + + @Override + protected Cache delegate() { + return this.delegate; + } + } + + final class EntrySet + extends AbstractCacheSet> { + EntrySet(ConcurrentMap map) { + super(map); + } + + @Override + public Iterator> iterator() { + return new EntryIterator(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + if (key == null) { + return false; + } + Object v = LocalCache.this.get(key); + return v != null && LocalCache.this.valueEquivalence.equivalent(e.getValue(), v); + } + + @Override + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + return key != null && LocalCache.this.remove(key, e.getValue()); + } + } + + final class Values + extends AbstractCollection { + private final ConcurrentMap map; + + Values(ConcurrentMap map) { + this.map = map; + } + + @Override + public int size() { + return this.map.size(); + } + + @Override + public boolean isEmpty() { + return this.map.isEmpty(); + } + + @Override + public void clear() { + this.map.clear(); + } + + @Override + public Iterator iterator() { + return new ValueIterator(); + } + + @Override + public boolean contains(Object o) { + return this.map.containsValue(o); + } + } + + final class KeySet + extends AbstractCacheSet { + KeySet(ConcurrentMap map) { + super(map); + } + + @Override + public Iterator iterator() { + return new KeyIterator(); + } + + @Override + public boolean contains(Object o) { + return this.map.containsKey(o); + } + + @Override + public boolean remove(Object o) { + return this.map.remove(o) != null; + } + } + + abstract class AbstractCacheSet + extends AbstractSet { + final ConcurrentMap map; + + AbstractCacheSet(ConcurrentMap map) { + this.map = map; + } + + @Override + public int size() { + return this.map.size(); + } + + @Override + public boolean isEmpty() { + return this.map.isEmpty(); + } + + @Override + public void clear() { + this.map.clear(); + } + } + + final class EntryIterator + extends HashIterator> { + EntryIterator() { + } + + @Override + public Map.Entry next() { + return this.nextEntry(); + } + } + + final class WriteThroughEntry + implements Map.Entry { + final K key; + V value; + + WriteThroughEntry(K key, V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public V getValue() { + return this.value; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry that = (Map.Entry)object; + return this.key.equals(that.getKey()) && this.value.equals(that.getValue()); + } + return false; + } + + @Override + public int hashCode() { + return this.key.hashCode() ^ this.value.hashCode(); + } + + @Override + public V setValue(V newValue) { + throw new UnsupportedOperationException(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.getKey())); + String string2 = String.valueOf(String.valueOf(this.getValue())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append("=").append(string2).toString(); + } + } + + final class ValueIterator + extends HashIterator { + ValueIterator() { + } + + @Override + public V next() { + return this.nextEntry().getValue(); + } + } + + final class KeyIterator + extends HashIterator { + KeyIterator() { + } + + @Override + public K next() { + return this.nextEntry().getKey(); + } + } + + abstract class HashIterator + implements Iterator { + int nextSegmentIndex; + int nextTableIndex; + Segment currentSegment; + AtomicReferenceArray> currentTable; + ReferenceEntry nextEntry; + WriteThroughEntry nextExternal; + WriteThroughEntry lastReturned; + + HashIterator() { + this.nextSegmentIndex = LocalCache.this.segments.length - 1; + this.nextTableIndex = -1; + this.advance(); + } + + @Override + public abstract T next(); + + final void advance() { + this.nextExternal = null; + if (this.nextInChain()) { + return; + } + if (this.nextInTable()) { + return; + } + while (this.nextSegmentIndex >= 0) { + this.currentSegment = LocalCache.this.segments[this.nextSegmentIndex--]; + if (this.currentSegment.count == 0) continue; + this.currentTable = this.currentSegment.table; + this.nextTableIndex = this.currentTable.length() - 1; + if (!this.nextInTable()) continue; + return; + } + } + + boolean nextInChain() { + if (this.nextEntry != null) { + this.nextEntry = this.nextEntry.getNext(); + while (this.nextEntry != null) { + if (this.advanceTo(this.nextEntry)) { + return true; + } + this.nextEntry = this.nextEntry.getNext(); + } + } + return false; + } + + boolean nextInTable() { + while (this.nextTableIndex >= 0) { + if ((this.nextEntry = this.currentTable.get(this.nextTableIndex--)) == null || !this.advanceTo(this.nextEntry) && !this.nextInChain()) continue; + return true; + } + return false; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean advanceTo(ReferenceEntry entry) { + try { + long now = LocalCache.this.ticker.read(); + Object key = entry.getKey(); + Object value = LocalCache.this.getLiveValue(entry, now); + if (value != null) { + this.nextExternal = new WriteThroughEntry(key, value); + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.currentSegment.postReadCleanup(); + } + } + + @Override + public boolean hasNext() { + return this.nextExternal != null; + } + + WriteThroughEntry nextEntry() { + if (this.nextExternal == null) { + throw new NoSuchElementException(); + } + this.lastReturned = this.nextExternal; + this.advance(); + return this.lastReturned; + } + + @Override + public void remove() { + Preconditions.checkState(this.lastReturned != null); + LocalCache.this.remove(this.lastReturned.getKey()); + this.lastReturned = null; + } + } + + static final class AccessQueue + extends AbstractQueue> { + final ReferenceEntry head = new AbstractReferenceEntry(){ + ReferenceEntry nextAccess = this; + ReferenceEntry previousAccess = this; + + @Override + public long getAccessTime() { + return Long.MAX_VALUE; + } + + @Override + public void setAccessTime(long time) { + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this.nextAccess; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + this.nextAccess = next; + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this.previousAccess; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + this.previousAccess = previous; + } + }; + + AccessQueue() { + } + + @Override + public boolean offer(ReferenceEntry entry) { + LocalCache.connectAccessOrder(entry.getPreviousInAccessQueue(), entry.getNextInAccessQueue()); + LocalCache.connectAccessOrder(this.head.getPreviousInAccessQueue(), entry); + LocalCache.connectAccessOrder(entry, this.head); + return true; + } + + @Override + public ReferenceEntry peek() { + ReferenceEntry next = this.head.getNextInAccessQueue(); + return next == this.head ? null : next; + } + + @Override + public ReferenceEntry poll() { + ReferenceEntry next = this.head.getNextInAccessQueue(); + if (next == this.head) { + return null; + } + this.remove(next); + return next; + } + + @Override + public boolean remove(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + ReferenceEntry previous = e.getPreviousInAccessQueue(); + ReferenceEntry next = e.getNextInAccessQueue(); + LocalCache.connectAccessOrder(previous, next); + LocalCache.nullifyAccessOrder(e); + return next != NullEntry.INSTANCE; + } + + @Override + public boolean contains(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + return e.getNextInAccessQueue() != NullEntry.INSTANCE; + } + + @Override + public boolean isEmpty() { + return this.head.getNextInAccessQueue() == this.head; + } + + @Override + public int size() { + int size = 0; + for (ReferenceEntry e = this.head.getNextInAccessQueue(); e != this.head; e = e.getNextInAccessQueue()) { + ++size; + } + return size; + } + + @Override + public void clear() { + ReferenceEntry e = this.head.getNextInAccessQueue(); + while (e != this.head) { + ReferenceEntry next = e.getNextInAccessQueue(); + LocalCache.nullifyAccessOrder(e); + e = next; + } + this.head.setNextInAccessQueue(this.head); + this.head.setPreviousInAccessQueue(this.head); + } + + @Override + public Iterator> iterator() { + return new AbstractSequentialIterator>((ReferenceEntry)this.peek()){ + + @Override + protected ReferenceEntry computeNext(ReferenceEntry previous) { + ReferenceEntry next = previous.getNextInAccessQueue(); + return next == AccessQueue.this.head ? null : next; + } + }; + } + } + + static final class WriteQueue + extends AbstractQueue> { + final ReferenceEntry head = new AbstractReferenceEntry(){ + ReferenceEntry nextWrite = this; + ReferenceEntry previousWrite = this; + + @Override + public long getWriteTime() { + return Long.MAX_VALUE; + } + + @Override + public void setWriteTime(long time) { + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this.nextWrite; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + this.nextWrite = next; + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this.previousWrite; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + this.previousWrite = previous; + } + }; + + WriteQueue() { + } + + @Override + public boolean offer(ReferenceEntry entry) { + LocalCache.connectWriteOrder(entry.getPreviousInWriteQueue(), entry.getNextInWriteQueue()); + LocalCache.connectWriteOrder(this.head.getPreviousInWriteQueue(), entry); + LocalCache.connectWriteOrder(entry, this.head); + return true; + } + + @Override + public ReferenceEntry peek() { + ReferenceEntry next = this.head.getNextInWriteQueue(); + return next == this.head ? null : next; + } + + @Override + public ReferenceEntry poll() { + ReferenceEntry next = this.head.getNextInWriteQueue(); + if (next == this.head) { + return null; + } + this.remove(next); + return next; + } + + @Override + public boolean remove(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + ReferenceEntry previous = e.getPreviousInWriteQueue(); + ReferenceEntry next = e.getNextInWriteQueue(); + LocalCache.connectWriteOrder(previous, next); + LocalCache.nullifyWriteOrder(e); + return next != NullEntry.INSTANCE; + } + + @Override + public boolean contains(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + return e.getNextInWriteQueue() != NullEntry.INSTANCE; + } + + @Override + public boolean isEmpty() { + return this.head.getNextInWriteQueue() == this.head; + } + + @Override + public int size() { + int size = 0; + for (ReferenceEntry e = this.head.getNextInWriteQueue(); e != this.head; e = e.getNextInWriteQueue()) { + ++size; + } + return size; + } + + @Override + public void clear() { + ReferenceEntry e = this.head.getNextInWriteQueue(); + while (e != this.head) { + ReferenceEntry next = e.getNextInWriteQueue(); + LocalCache.nullifyWriteOrder(e); + e = next; + } + this.head.setNextInWriteQueue(this.head); + this.head.setPreviousInWriteQueue(this.head); + } + + @Override + public Iterator> iterator() { + return new AbstractSequentialIterator>((ReferenceEntry)this.peek()){ + + @Override + protected ReferenceEntry computeNext(ReferenceEntry previous) { + ReferenceEntry next = previous.getNextInWriteQueue(); + return next == WriteQueue.this.head ? null : next; + } + }; + } + } + + static class LoadingValueReference + implements ValueReference { + volatile ValueReference oldValue; + final SettableFuture futureValue = SettableFuture.create(); + final Stopwatch stopwatch = Stopwatch.createUnstarted(); + + public LoadingValueReference() { + this(LocalCache.unset()); + } + + public LoadingValueReference(ValueReference oldValue) { + this.oldValue = oldValue; + } + + @Override + public boolean isLoading() { + return true; + } + + @Override + public boolean isActive() { + return this.oldValue.isActive(); + } + + @Override + public int getWeight() { + return this.oldValue.getWeight(); + } + + public boolean set(@Nullable V newValue) { + return this.futureValue.set(newValue); + } + + public boolean setException(Throwable t) { + return this.futureValue.setException(t); + } + + private ListenableFuture fullyFailedFuture(Throwable t) { + return Futures.immediateFailedFuture(t); + } + + @Override + public void notifyNewValue(@Nullable V newValue) { + if (newValue != null) { + this.set(newValue); + } else { + this.oldValue = LocalCache.unset(); + } + } + + public ListenableFuture loadFuture(K key, CacheLoader loader) { + this.stopwatch.start(); + V previousValue = this.oldValue.get(); + try { + if (previousValue == null) { + V newValue = loader.load(key); + return this.set(newValue) ? this.futureValue : Futures.immediateFuture(newValue); + } + ListenableFuture newValue = loader.reload(key, previousValue); + if (newValue == null) { + return Futures.immediateFuture(null); + } + return Futures.transform(newValue, new Function(){ + + @Override + public V apply(V newValue) { + LoadingValueReference.this.set(newValue); + return newValue; + } + }); + } + catch (Throwable t) { + if (t instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + return this.setException(t) ? this.futureValue : this.fullyFailedFuture(t); + } + } + + public long elapsedNanos() { + return this.stopwatch.elapsed(TimeUnit.NANOSECONDS); + } + + @Override + public V waitForValue() throws ExecutionException { + return Uninterruptibles.getUninterruptibly(this.futureValue); + } + + @Override + public V get() { + return this.oldValue.get(); + } + + public ValueReference getOldValue() { + return this.oldValue; + } + + @Override + public ReferenceEntry getEntry() { + return null; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, @Nullable V value, ReferenceEntry entry) { + return this; + } + } + + static class Segment + extends ReentrantLock { + final LocalCache map; + volatile int count; + @GuardedBy(value="this") + long totalWeight; + int modCount; + int threshold; + volatile AtomicReferenceArray> table; + final long maxSegmentWeight; + final ReferenceQueue keyReferenceQueue; + final ReferenceQueue valueReferenceQueue; + final Queue> recencyQueue; + final AtomicInteger readCount = new AtomicInteger(); + @GuardedBy(value="this") + final Queue> writeQueue; + @GuardedBy(value="this") + final Queue> accessQueue; + final AbstractCache.StatsCounter statsCounter; + + Segment(LocalCache map, int initialCapacity, long maxSegmentWeight, AbstractCache.StatsCounter statsCounter) { + this.map = map; + this.maxSegmentWeight = maxSegmentWeight; + this.statsCounter = Preconditions.checkNotNull(statsCounter); + this.initTable(this.newEntryArray(initialCapacity)); + this.keyReferenceQueue = map.usesKeyReferences() ? new ReferenceQueue() : null; + this.valueReferenceQueue = map.usesValueReferences() ? new ReferenceQueue() : null; + this.recencyQueue = map.usesAccessQueue() ? new ConcurrentLinkedQueue() : LocalCache.discardingQueue(); + this.writeQueue = map.usesWriteQueue() ? new WriteQueue() : LocalCache.discardingQueue(); + this.accessQueue = map.usesAccessQueue() ? new AccessQueue() : LocalCache.discardingQueue(); + } + + AtomicReferenceArray> newEntryArray(int size) { + return new AtomicReferenceArray>(size); + } + + void initTable(AtomicReferenceArray> newTable) { + this.threshold = newTable.length() * 3 / 4; + if (!this.map.customWeigher() && (long)this.threshold == this.maxSegmentWeight) { + ++this.threshold; + } + this.table = newTable; + } + + @GuardedBy(value="this") + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) { + return this.map.entryFactory.newEntry(this, Preconditions.checkNotNull(key), hash, next); + } + + @GuardedBy(value="this") + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) { + if (original.getKey() == null) { + return null; + } + ValueReference valueReference = original.getValueReference(); + V value = valueReference.get(); + if (value == null && valueReference.isActive()) { + return null; + } + ReferenceEntry newEntry = this.map.entryFactory.copyEntry(this, original, newNext); + newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, value, newEntry)); + return newEntry; + } + + @GuardedBy(value="this") + void setValue(ReferenceEntry entry, K key, V value, long now) { + ValueReference previous = entry.getValueReference(); + int weight = this.map.weigher.weigh(key, value); + Preconditions.checkState(weight >= 0, "Weights must be non-negative"); + ValueReference valueReference = this.map.valueStrength.referenceValue(this, entry, value, weight); + entry.setValueReference(valueReference); + this.recordWrite(entry, weight, now); + previous.notifyNewValue(value); + } + + V get(K key, int hash, CacheLoader loader) throws ExecutionException { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(loader); + try { + ReferenceEntry e; + if (this.count != 0 && (e = this.getEntry(key, hash)) != null) { + long now = this.map.ticker.read(); + V value = this.getLiveValue(e, now); + if (value != null) { + this.recordRead(e, now); + this.statsCounter.recordHits(1); + V v = this.scheduleRefresh(e, key, hash, value, now, loader); + return v; + } + ValueReference valueReference = e.getValueReference(); + if (valueReference.isLoading()) { + V v = this.waitForLoadingValue(e, key, valueReference); + return v; + } + } + e = this.lockedGetOrLoad(key, hash, loader); + return (V)e; + } + catch (ExecutionException ee) { + Throwable cause = ee.getCause(); + if (cause instanceof Error) { + throw new ExecutionError((Error)cause); + } + if (cause instanceof RuntimeException) { + throw new UncheckedExecutionException(cause); + } + throw ee; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V lockedGetOrLoad(K key, int hash, CacheLoader loader) throws ExecutionException { + ReferenceEntry e; + ValueReference valueReference = null; + LoadingValueReference loadingValueReference = null; + boolean createNewEntry = true; + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + valueReference = e.getValueReference(); + if (valueReference.isLoading()) { + createNewEntry = false; + break; + } + V value = valueReference.get(); + if (value == null) { + this.enqueueNotification(entryKey, hash, valueReference, RemovalCause.COLLECTED); + } else if (this.map.isExpired(e, now)) { + this.enqueueNotification(entryKey, hash, valueReference, RemovalCause.EXPIRED); + } else { + this.recordLockedRead(e, now); + this.statsCounter.recordHits(1); + V v = value; + return v; + } + this.writeQueue.remove(e); + this.accessQueue.remove(e); + this.count = newCount; + break; + } + if (createNewEntry) { + loadingValueReference = new LoadingValueReference(); + if (e == null) { + e = this.newEntry(key, hash, first); + e.setValueReference(loadingValueReference); + table.set(index, e); + } else { + e.setValueReference(loadingValueReference); + } + } + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + if (createNewEntry) { + try { + ReferenceEntry referenceEntry = e; + synchronized (referenceEntry) { + Object v = this.loadSync(key, hash, loadingValueReference, loader); + return v; + } + } + finally { + this.statsCounter.recordMisses(1); + } + } + return this.waitForLoadingValue(e, key, valueReference); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V waitForLoadingValue(ReferenceEntry e, K key, ValueReference valueReference) throws ExecutionException { + if (!valueReference.isLoading()) { + throw new AssertionError(); + } + Preconditions.checkState(!Thread.holdsLock(e), "Recursive load of: %s", key); + try { + V value = valueReference.waitForValue(); + if (value == null) { + String string = String.valueOf(String.valueOf(key)); + throw new CacheLoader.InvalidCacheLoadException(new StringBuilder(35 + string.length()).append("CacheLoader returned null for key ").append(string).append(".").toString()); + } + long now = this.map.ticker.read(); + this.recordRead(e, now); + V v = value; + return v; + } + finally { + this.statsCounter.recordMisses(1); + } + } + + V loadSync(K key, int hash, LoadingValueReference loadingValueReference, CacheLoader loader) throws ExecutionException { + ListenableFuture loadingFuture = loadingValueReference.loadFuture((K)key, loader); + return this.getAndRecordStats(key, hash, loadingValueReference, loadingFuture); + } + + ListenableFuture loadAsync(final K key, final int hash, final LoadingValueReference loadingValueReference, CacheLoader loader) { + final ListenableFuture loadingFuture = loadingValueReference.loadFuture((K)key, loader); + loadingFuture.addListener(new Runnable(){ + + @Override + public void run() { + try { + Object newValue = Segment.this.getAndRecordStats(key, hash, loadingValueReference, loadingFuture); + } + catch (Throwable t) { + logger.log(Level.WARNING, "Exception thrown during refresh", t); + loadingValueReference.setException(t); + } + } + }, MoreExecutors.directExecutor()); + return loadingFuture; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V getAndRecordStats(K key, int hash, LoadingValueReference loadingValueReference, ListenableFuture newValue) throws ExecutionException { + V value = null; + try { + value = Uninterruptibles.getUninterruptibly(newValue); + if (value == null) { + String string = String.valueOf(String.valueOf(key)); + throw new CacheLoader.InvalidCacheLoadException(new StringBuilder(35 + string.length()).append("CacheLoader returned null for key ").append(string).append(".").toString()); + } + this.statsCounter.recordLoadSuccess(loadingValueReference.elapsedNanos()); + this.storeLoadedValue(key, hash, loadingValueReference, value); + V v = value; + return v; + } + finally { + if (value == null) { + this.statsCounter.recordLoadException(loadingValueReference.elapsedNanos()); + this.removeLoadingValue(key, hash, loadingValueReference); + } + } + } + + V scheduleRefresh(ReferenceEntry entry, K key, int hash, V oldValue, long now, CacheLoader loader) { + V newValue; + if (this.map.refreshes() && now - entry.getWriteTime() > this.map.refreshNanos && !entry.getValueReference().isLoading() && (newValue = this.refresh(key, hash, loader, true)) != null) { + return newValue; + } + return oldValue; + } + + @Nullable + V refresh(K key, int hash, CacheLoader loader, boolean checkTime) { + LoadingValueReference loadingValueReference = this.insertLoadingValueReference(key, hash, checkTime); + if (loadingValueReference == null) { + return null; + } + ListenableFuture result = this.loadAsync(key, hash, loadingValueReference, loader); + if (result.isDone()) { + try { + return Uninterruptibles.getUninterruptibly(result); + } + catch (Throwable t) { + // empty catch block + } + } + return null; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Nullable + LoadingValueReference insertLoadingValueReference(K key, int hash, boolean checkTime) { + ReferenceEntry e = null; + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + if (valueReference.isLoading() || checkTime && now - e.getWriteTime() < this.map.refreshNanos) { + LoadingValueReference loadingValueReference = null; + return loadingValueReference; + } + ++this.modCount; + LoadingValueReference loadingValueReference = new LoadingValueReference(valueReference); + e.setValueReference(loadingValueReference); + LoadingValueReference loadingValueReference2 = loadingValueReference; + return loadingValueReference2; + } + ++this.modCount; + LoadingValueReference loadingValueReference = new LoadingValueReference(); + e = this.newEntry(key, hash, first); + e.setValueReference(loadingValueReference); + table.set(index, e); + LoadingValueReference loadingValueReference3 = loadingValueReference; + return loadingValueReference3; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void tryDrainReferenceQueues() { + if (this.tryLock()) { + try { + this.drainReferenceQueues(); + } + finally { + this.unlock(); + } + } + } + + @GuardedBy(value="this") + void drainReferenceQueues() { + if (this.map.usesKeyReferences()) { + this.drainKeyReferenceQueue(); + } + if (this.map.usesValueReferences()) { + this.drainValueReferenceQueue(); + } + } + + @GuardedBy(value="this") + void drainKeyReferenceQueue() { + Reference ref; + int i = 0; + while ((ref = this.keyReferenceQueue.poll()) != null) { + ReferenceEntry entry = (ReferenceEntry)((Object)ref); + this.map.reclaimKey(entry); + if (++i != 16) continue; + break; + } + } + + @GuardedBy(value="this") + void drainValueReferenceQueue() { + Reference ref; + int i = 0; + while ((ref = this.valueReferenceQueue.poll()) != null) { + ValueReference valueReference = (ValueReference)((Object)ref); + this.map.reclaimValue(valueReference); + if (++i != 16) continue; + break; + } + } + + void clearReferenceQueues() { + if (this.map.usesKeyReferences()) { + this.clearKeyReferenceQueue(); + } + if (this.map.usesValueReferences()) { + this.clearValueReferenceQueue(); + } + } + + void clearKeyReferenceQueue() { + while (this.keyReferenceQueue.poll() != null) { + } + } + + void clearValueReferenceQueue() { + while (this.valueReferenceQueue.poll() != null) { + } + } + + void recordRead(ReferenceEntry entry, long now) { + if (this.map.recordsAccess()) { + entry.setAccessTime(now); + } + this.recencyQueue.add(entry); + } + + @GuardedBy(value="this") + void recordLockedRead(ReferenceEntry entry, long now) { + if (this.map.recordsAccess()) { + entry.setAccessTime(now); + } + this.accessQueue.add(entry); + } + + @GuardedBy(value="this") + void recordWrite(ReferenceEntry entry, int weight, long now) { + this.drainRecencyQueue(); + this.totalWeight += (long)weight; + if (this.map.recordsAccess()) { + entry.setAccessTime(now); + } + if (this.map.recordsWrite()) { + entry.setWriteTime(now); + } + this.accessQueue.add(entry); + this.writeQueue.add(entry); + } + + @GuardedBy(value="this") + void drainRecencyQueue() { + ReferenceEntry e; + while ((e = this.recencyQueue.poll()) != null) { + if (!this.accessQueue.contains(e)) continue; + this.accessQueue.add(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void tryExpireEntries(long now) { + if (this.tryLock()) { + try { + this.expireEntries(now); + } + finally { + this.unlock(); + } + } + } + + @GuardedBy(value="this") + void expireEntries(long now) { + ReferenceEntry e; + this.drainRecencyQueue(); + while ((e = this.writeQueue.peek()) != null && this.map.isExpired(e, now)) { + if (!this.removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + while ((e = this.accessQueue.peek()) != null && this.map.isExpired(e, now)) { + if (!this.removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + } + + @GuardedBy(value="this") + void enqueueNotification(ReferenceEntry entry, RemovalCause cause) { + this.enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference(), cause); + } + + @GuardedBy(value="this") + void enqueueNotification(@Nullable K key, int hash, ValueReference valueReference, RemovalCause cause) { + this.totalWeight -= (long)valueReference.getWeight(); + if (cause.wasEvicted()) { + this.statsCounter.recordEviction(); + } + if (this.map.removalNotificationQueue != DISCARDING_QUEUE) { + V value = valueReference.get(); + RemovalNotification notification = new RemovalNotification(key, value, cause); + this.map.removalNotificationQueue.offer(notification); + } + } + + @GuardedBy(value="this") + void evictEntries() { + if (!this.map.evictsBySize()) { + return; + } + this.drainRecencyQueue(); + while (this.totalWeight > this.maxSegmentWeight) { + ReferenceEntry e = this.getNextEvictable(); + if (!this.removeEntry(e, e.getHash(), RemovalCause.SIZE)) { + throw new AssertionError(); + } + } + } + + @GuardedBy(value="this") + ReferenceEntry getNextEvictable() { + for (ReferenceEntry referenceEntry : this.accessQueue) { + int weight = referenceEntry.getValueReference().getWeight(); + if (weight <= 0) continue; + return referenceEntry; + } + throw new AssertionError(); + } + + ReferenceEntry getFirst(int hash) { + AtomicReferenceArray> table = this.table; + return table.get(hash & table.length() - 1); + } + + @Nullable + ReferenceEntry getEntry(Object key, int hash) { + for (ReferenceEntry e = this.getFirst(hash); e != null; e = e.getNext()) { + if (e.getHash() != hash) continue; + K entryKey = e.getKey(); + if (entryKey == null) { + this.tryDrainReferenceQueues(); + continue; + } + if (!this.map.keyEquivalence.equivalent(key, entryKey)) continue; + return e; + } + return null; + } + + @Nullable + ReferenceEntry getLiveEntry(Object key, int hash, long now) { + ReferenceEntry e = this.getEntry(key, hash); + if (e == null) { + return null; + } + if (this.map.isExpired(e, now)) { + this.tryExpireEntries(now); + return null; + } + return e; + } + + V getLiveValue(ReferenceEntry entry, long now) { + if (entry.getKey() == null) { + this.tryDrainReferenceQueues(); + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + this.tryDrainReferenceQueues(); + return null; + } + if (this.map.isExpired(entry, now)) { + this.tryExpireEntries(now); + return null; + } + return value; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Nullable + V get(Object key, int hash) { + try { + if (this.count != 0) { + long now = this.map.ticker.read(); + ReferenceEntry e = this.getLiveEntry(key, hash, now); + if (e == null) { + V v = null; + return v; + } + V value = e.getValueReference().get(); + if (value != null) { + this.recordRead(e, now); + V v = this.scheduleRefresh(e, e.getKey(), hash, value, now, this.map.defaultLoader); + return v; + } + this.tryDrainReferenceQueues(); + } + V v = null; + return v; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean containsKey(Object key, int hash) { + try { + if (this.count != 0) { + long now = this.map.ticker.read(); + ReferenceEntry e = this.getLiveEntry(key, hash, now); + if (e == null) { + boolean bl = false; + return bl; + } + boolean bl = e.getValueReference().get() != null; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @VisibleForTesting + boolean containsValue(Object value) { + try { + if (this.count != 0) { + long now = this.map.ticker.read(); + AtomicReferenceArray> table = this.table; + int length = table.length(); + for (int i = 0; i < length; ++i) { + for (ReferenceEntry e = table.get(i); e != null; e = e.getNext()) { + V entryValue = this.getLiveValue(e, now); + if (entryValue == null || !this.map.valueEquivalence.equivalent(value, entryValue)) continue; + boolean bl = true; + return bl; + } + } + } + boolean bl = false; + return bl; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Nullable + V put(K key, int hash, V value, boolean onlyIfAbsent) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + int newCount = this.count + 1; + if (newCount > this.threshold) { + this.expand(); + newCount = this.count + 1; + } + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + ++this.modCount; + if (valueReference.isActive()) { + this.enqueueNotification(key, hash, valueReference, RemovalCause.COLLECTED); + this.setValue(e, key, value, now); + newCount = this.count; + } else { + this.setValue(e, key, value, now); + newCount = this.count + 1; + } + this.count = newCount; + this.evictEntries(); + V v = null; + return v; + } + if (onlyIfAbsent) { + this.recordLockedRead(e, now); + V v = entryValue; + return v; + } + ++this.modCount; + this.enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + this.setValue(e, key, value, now); + this.evictEntries(); + V v = entryValue; + return v; + } + ++this.modCount; + ReferenceEntry newEntry = this.newEntry(key, hash, first); + this.setValue(newEntry, key, value, now); + table.set(index, newEntry); + this.count = newCount = this.count + 1; + this.evictEntries(); + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + @GuardedBy(value="this") + void expand() { + AtomicReferenceArray> oldTable = this.table; + int oldCapacity = oldTable.length(); + if (oldCapacity >= 0x40000000) { + return; + } + int newCount = this.count; + AtomicReferenceArray> newTable = this.newEntryArray(oldCapacity << 1); + this.threshold = newTable.length() * 3 / 4; + int newMask = newTable.length() - 1; + for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) { + int newIndex; + ReferenceEntry e; + ReferenceEntry head = oldTable.get(oldIndex); + if (head == null) continue; + ReferenceEntry next = head.getNext(); + int headIndex = head.getHash() & newMask; + if (next == null) { + newTable.set(headIndex, head); + continue; + } + ReferenceEntry tail = head; + int tailIndex = headIndex; + for (e = next; e != null; e = e.getNext()) { + newIndex = e.getHash() & newMask; + if (newIndex == tailIndex) continue; + tailIndex = newIndex; + tail = e; + } + newTable.set(tailIndex, tail); + for (e = head; e != tail; e = e.getNext()) { + newIndex = e.getHash() & newMask; + ReferenceEntry newNext = newTable.get(newIndex); + ReferenceEntry newFirst = this.copyEntry(e, newNext); + if (newFirst != null) { + newTable.set(newIndex, newFirst); + continue; + } + this.removeCollectedEntry(e); + --newCount; + } + } + this.table = newTable; + this.count = newCount; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean replace(K key, int hash, V oldValue, V newValue) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + if (valueReference.isActive()) { + int newCount = this.count - 1; + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + } + boolean bl = false; + return bl; + } + if (this.map.valueEquivalence.equivalent(oldValue, entryValue)) { + ++this.modCount; + this.enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + this.setValue(e, key, newValue, now); + this.evictEntries(); + boolean bl = true; + return bl; + } + this.recordLockedRead(e, now); + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Nullable + V replace(K key, int hash, V newValue) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + if (valueReference.isActive()) { + int newCount = this.count - 1; + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + } + V v = null; + return v; + } + ++this.modCount; + this.enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + this.setValue(e, key, newValue, now); + this.evictEntries(); + V v = entryValue; + return v; + } + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Nullable + V remove(Object key, int hash) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + RemovalCause cause; + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue != null) { + cause = RemovalCause.EXPLICIT; + } else if (valueReference.isActive()) { + cause = RemovalCause.COLLECTED; + } else { + V v = null; + return v; + } + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, entryKey, hash, valueReference, cause); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + V v = entryValue; + return v; + } + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean storeLoadedValue(K key, int hash, LoadingValueReference oldValueReference, V newValue) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + int newCount = this.count + 1; + if (newCount > this.threshold) { + this.expand(); + newCount = this.count + 1; + } + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (oldValueReference == valueReference || entryValue == null && valueReference != UNSET) { + ++this.modCount; + if (oldValueReference.isActive()) { + RemovalCause cause = entryValue == null ? RemovalCause.COLLECTED : RemovalCause.REPLACED; + this.enqueueNotification(key, hash, oldValueReference, cause); + --newCount; + } + this.setValue(e, key, newValue, now); + this.count = newCount; + this.evictEntries(); + boolean bl = true; + return bl; + } + valueReference = new WeightedStrongValueReference(newValue, 0); + this.enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + boolean bl = false; + return bl; + } + ++this.modCount; + ReferenceEntry newEntry = this.newEntry(key, hash, first); + this.setValue(newEntry, key, newValue, now); + table.set(index, newEntry); + this.count = newCount; + this.evictEntries(); + boolean bl = true; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean remove(Object key, int hash, Object value) { + this.lock(); + try { + ReferenceEntry first; + long now = this.map.ticker.read(); + this.preWriteCleanup(now); + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + RemovalCause cause; + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (this.map.valueEquivalence.equivalent(value, entryValue)) { + cause = RemovalCause.EXPLICIT; + } else if (entryValue == null && valueReference.isActive()) { + cause = RemovalCause.COLLECTED; + } else { + boolean bl = false; + return bl; + } + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, entryKey, hash, valueReference, cause); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = cause == RemovalCause.EXPLICIT; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void clear() { + if (this.count != 0) { + this.lock(); + try { + int i; + AtomicReferenceArray> table = this.table; + for (i = 0; i < table.length(); ++i) { + for (ReferenceEntry e = table.get(i); e != null; e = e.getNext()) { + if (!e.getValueReference().isActive()) continue; + this.enqueueNotification(e, RemovalCause.EXPLICIT); + } + } + for (i = 0; i < table.length(); ++i) { + table.set(i, null); + } + this.clearReferenceQueues(); + this.writeQueue.clear(); + this.accessQueue.clear(); + this.readCount.set(0); + ++this.modCount; + this.count = 0; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + } + + @Nullable + @GuardedBy(value="this") + ReferenceEntry removeValueFromChain(ReferenceEntry first, ReferenceEntry entry, @Nullable K key, int hash, ValueReference valueReference, RemovalCause cause) { + this.enqueueNotification(key, hash, valueReference, cause); + this.writeQueue.remove(entry); + this.accessQueue.remove(entry); + if (valueReference.isLoading()) { + valueReference.notifyNewValue(null); + return first; + } + return this.removeEntryFromChain(first, entry); + } + + @Nullable + @GuardedBy(value="this") + ReferenceEntry removeEntryFromChain(ReferenceEntry first, ReferenceEntry entry) { + int newCount = this.count; + ReferenceEntry newFirst = entry.getNext(); + for (ReferenceEntry e = first; e != entry; e = e.getNext()) { + ReferenceEntry next = this.copyEntry(e, newFirst); + if (next != null) { + newFirst = next; + continue; + } + this.removeCollectedEntry(e); + --newCount; + } + this.count = newCount; + return newFirst; + } + + @GuardedBy(value="this") + void removeCollectedEntry(ReferenceEntry entry) { + this.enqueueNotification(entry, RemovalCause.COLLECTED); + this.writeQueue.remove(entry); + this.accessQueue.remove(entry); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean reclaimKey(ReferenceEntry entry, int hash) { + this.lock(); + try { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + if (e != entry) continue; + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, e.getKey(), hash, e.getValueReference(), RemovalCause.COLLECTED); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean reclaimValue(K key, int hash, ValueReference valueReference) { + this.lock(); + try { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference v = e.getValueReference(); + if (v == valueReference) { + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + if (!this.isHeldByCurrentThread()) { + this.postWriteCleanup(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean removeLoadingValue(K key, int hash, LoadingValueReference valueReference) { + this.lock(); + try { + ReferenceEntry first; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference v = e.getValueReference(); + if (v == valueReference) { + if (valueReference.isActive()) { + e.setValueReference(valueReference.getOldValue()); + } else { + ReferenceEntry newFirst = this.removeEntryFromChain(first, e); + table.set(index, newFirst); + } + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + @GuardedBy(value="this") + boolean removeEntry(ReferenceEntry entry, int hash, RemovalCause cause) { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + if (e != entry) continue; + ++this.modCount; + ReferenceEntry newFirst = this.removeValueFromChain(first, e, e.getKey(), hash, e.getValueReference(), cause); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + return true; + } + return false; + } + + void postReadCleanup() { + if ((this.readCount.incrementAndGet() & 0x3F) == 0) { + this.cleanUp(); + } + } + + @GuardedBy(value="this") + void preWriteCleanup(long now) { + this.runLockedCleanup(now); + } + + void postWriteCleanup() { + this.runUnlockedCleanup(); + } + + void cleanUp() { + long now = this.map.ticker.read(); + this.runLockedCleanup(now); + this.runUnlockedCleanup(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void runLockedCleanup(long now) { + if (this.tryLock()) { + try { + this.drainReferenceQueues(); + this.expireEntries(now); + this.readCount.set(0); + } + finally { + this.unlock(); + } + } + } + + void runUnlockedCleanup() { + if (!this.isHeldByCurrentThread()) { + this.map.processPendingNotifications(); + } + } + } + + static final class WeightedStrongValueReference + extends StrongValueReference { + final int weight; + + WeightedStrongValueReference(V referent, int weight) { + super(referent); + this.weight = weight; + } + + @Override + public int getWeight() { + return this.weight; + } + } + + static final class WeightedSoftValueReference + extends SoftValueReference { + final int weight; + + WeightedSoftValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry, int weight) { + super(queue, referent, entry); + this.weight = weight; + } + + @Override + public int getWeight() { + return this.weight; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new WeightedSoftValueReference(queue, value, entry, this.weight); + } + } + + static final class WeightedWeakValueReference + extends WeakValueReference { + final int weight; + + WeightedWeakValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry, int weight) { + super(queue, referent, entry); + this.weight = weight; + } + + @Override + public int getWeight() { + return this.weight; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new WeightedWeakValueReference(queue, value, entry, this.weight); + } + } + + static class StrongValueReference + implements ValueReference { + final V referent; + + StrongValueReference(V referent) { + this.referent = referent; + } + + @Override + public V get() { + return this.referent; + } + + @Override + public int getWeight() { + return 1; + } + + @Override + public ReferenceEntry getEntry() { + return null; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return this; + } + + @Override + public boolean isLoading() { + return false; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public V waitForValue() { + return this.get(); + } + + @Override + public void notifyNewValue(V newValue) { + } + } + + static class SoftValueReference + extends SoftReference + implements ValueReference { + final ReferenceEntry entry; + + SoftValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry) { + super(referent, queue); + this.entry = entry; + } + + @Override + public int getWeight() { + return 1; + } + + @Override + public ReferenceEntry getEntry() { + return this.entry; + } + + @Override + public void notifyNewValue(V newValue) { + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new SoftValueReference(queue, value, entry); + } + + @Override + public boolean isLoading() { + return false; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public V waitForValue() { + return (V)this.get(); + } + } + + static class WeakValueReference + extends WeakReference + implements ValueReference { + final ReferenceEntry entry; + + WeakValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry) { + super(referent, queue); + this.entry = entry; + } + + @Override + public int getWeight() { + return 1; + } + + @Override + public ReferenceEntry getEntry() { + return this.entry; + } + + @Override + public void notifyNewValue(V newValue) { + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new WeakValueReference(queue, value, entry); + } + + @Override + public boolean isLoading() { + return false; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public V waitForValue() { + return (V)this.get(); + } + } + + static final class WeakAccessWriteEntry + extends WeakEntry { + volatile long accessTime = Long.MAX_VALUE; + ReferenceEntry nextAccess = LocalCache.nullEntry(); + ReferenceEntry previousAccess = LocalCache.nullEntry(); + volatile long writeTime = Long.MAX_VALUE; + ReferenceEntry nextWrite = LocalCache.nullEntry(); + ReferenceEntry previousWrite = LocalCache.nullEntry(); + + WeakAccessWriteEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getAccessTime() { + return this.accessTime; + } + + @Override + public void setAccessTime(long time) { + this.accessTime = time; + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this.nextAccess; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + this.nextAccess = next; + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this.previousAccess; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + this.previousAccess = previous; + } + + @Override + public long getWriteTime() { + return this.writeTime; + } + + @Override + public void setWriteTime(long time) { + this.writeTime = time; + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this.nextWrite; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + this.nextWrite = next; + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this.previousWrite; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + this.previousWrite = previous; + } + } + + static final class WeakWriteEntry + extends WeakEntry { + volatile long writeTime = Long.MAX_VALUE; + ReferenceEntry nextWrite = LocalCache.nullEntry(); + ReferenceEntry previousWrite = LocalCache.nullEntry(); + + WeakWriteEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getWriteTime() { + return this.writeTime; + } + + @Override + public void setWriteTime(long time) { + this.writeTime = time; + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this.nextWrite; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + this.nextWrite = next; + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this.previousWrite; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + this.previousWrite = previous; + } + } + + static final class WeakAccessEntry + extends WeakEntry { + volatile long accessTime = Long.MAX_VALUE; + ReferenceEntry nextAccess = LocalCache.nullEntry(); + ReferenceEntry previousAccess = LocalCache.nullEntry(); + + WeakAccessEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getAccessTime() { + return this.accessTime; + } + + @Override + public void setAccessTime(long time) { + this.accessTime = time; + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this.nextAccess; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + this.nextAccess = next; + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this.previousAccess; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + this.previousAccess = previous; + } + } + + static class WeakEntry + extends WeakReference + implements ReferenceEntry { + final int hash; + final ReferenceEntry next; + volatile ValueReference valueReference = LocalCache.unset(); + + WeakEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(key, queue); + this.hash = hash; + this.next = next; + } + + @Override + public K getKey() { + return (K)this.get(); + } + + @Override + public long getAccessTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setAccessTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public long getWriteTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setWriteTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ValueReference getValueReference() { + return this.valueReference; + } + + @Override + public void setValueReference(ValueReference valueReference) { + this.valueReference = valueReference; + } + + @Override + public int getHash() { + return this.hash; + } + + @Override + public ReferenceEntry getNext() { + return this.next; + } + } + + static final class StrongAccessWriteEntry + extends StrongEntry { + volatile long accessTime = Long.MAX_VALUE; + ReferenceEntry nextAccess = LocalCache.nullEntry(); + ReferenceEntry previousAccess = LocalCache.nullEntry(); + volatile long writeTime = Long.MAX_VALUE; + ReferenceEntry nextWrite = LocalCache.nullEntry(); + ReferenceEntry previousWrite = LocalCache.nullEntry(); + + StrongAccessWriteEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public long getAccessTime() { + return this.accessTime; + } + + @Override + public void setAccessTime(long time) { + this.accessTime = time; + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this.nextAccess; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + this.nextAccess = next; + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this.previousAccess; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + this.previousAccess = previous; + } + + @Override + public long getWriteTime() { + return this.writeTime; + } + + @Override + public void setWriteTime(long time) { + this.writeTime = time; + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this.nextWrite; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + this.nextWrite = next; + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this.previousWrite; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + this.previousWrite = previous; + } + } + + static final class StrongWriteEntry + extends StrongEntry { + volatile long writeTime = Long.MAX_VALUE; + ReferenceEntry nextWrite = LocalCache.nullEntry(); + ReferenceEntry previousWrite = LocalCache.nullEntry(); + + StrongWriteEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public long getWriteTime() { + return this.writeTime; + } + + @Override + public void setWriteTime(long time) { + this.writeTime = time; + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this.nextWrite; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + this.nextWrite = next; + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this.previousWrite; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + this.previousWrite = previous; + } + } + + static final class StrongAccessEntry + extends StrongEntry { + volatile long accessTime = Long.MAX_VALUE; + ReferenceEntry nextAccess = LocalCache.nullEntry(); + ReferenceEntry previousAccess = LocalCache.nullEntry(); + + StrongAccessEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public long getAccessTime() { + return this.accessTime; + } + + @Override + public void setAccessTime(long time) { + this.accessTime = time; + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this.nextAccess; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + this.nextAccess = next; + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this.previousAccess; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + this.previousAccess = previous; + } + } + + static class StrongEntry + extends AbstractReferenceEntry { + final K key; + final int hash; + final ReferenceEntry next; + volatile ValueReference valueReference = LocalCache.unset(); + + StrongEntry(K key, int hash, @Nullable ReferenceEntry next) { + this.key = key; + this.hash = hash; + this.next = next; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public ValueReference getValueReference() { + return this.valueReference; + } + + @Override + public void setValueReference(ValueReference valueReference) { + this.valueReference = valueReference; + } + + @Override + public int getHash() { + return this.hash; + } + + @Override + public ReferenceEntry getNext() { + return this.next; + } + } + + static abstract class AbstractReferenceEntry + implements ReferenceEntry { + AbstractReferenceEntry() { + } + + @Override + public ValueReference getValueReference() { + throw new UnsupportedOperationException(); + } + + @Override + public void setValueReference(ValueReference valueReference) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNext() { + throw new UnsupportedOperationException(); + } + + @Override + public int getHash() { + throw new UnsupportedOperationException(); + } + + @Override + public K getKey() { + throw new UnsupportedOperationException(); + } + + @Override + public long getAccessTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setAccessTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public long getWriteTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setWriteTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + } + + private static enum NullEntry implements ReferenceEntry + { + INSTANCE; + + + @Override + public ValueReference getValueReference() { + return null; + } + + @Override + public void setValueReference(ValueReference valueReference) { + } + + @Override + public ReferenceEntry getNext() { + return null; + } + + @Override + public int getHash() { + return 0; + } + + @Override + public Object getKey() { + return null; + } + + @Override + public long getAccessTime() { + return 0L; + } + + @Override + public void setAccessTime(long time) { + } + + @Override + public ReferenceEntry getNextInAccessQueue() { + return this; + } + + @Override + public void setNextInAccessQueue(ReferenceEntry next) { + } + + @Override + public ReferenceEntry getPreviousInAccessQueue() { + return this; + } + + @Override + public void setPreviousInAccessQueue(ReferenceEntry previous) { + } + + @Override + public long getWriteTime() { + return 0L; + } + + @Override + public void setWriteTime(long time) { + } + + @Override + public ReferenceEntry getNextInWriteQueue() { + return this; + } + + @Override + public void setNextInWriteQueue(ReferenceEntry next) { + } + + @Override + public ReferenceEntry getPreviousInWriteQueue() { + return this; + } + + @Override + public void setPreviousInWriteQueue(ReferenceEntry previous) { + } + } + + static interface ReferenceEntry { + public ValueReference getValueReference(); + + public void setValueReference(ValueReference var1); + + @Nullable + public ReferenceEntry getNext(); + + public int getHash(); + + @Nullable + public K getKey(); + + public long getAccessTime(); + + public void setAccessTime(long var1); + + public ReferenceEntry getNextInAccessQueue(); + + public void setNextInAccessQueue(ReferenceEntry var1); + + public ReferenceEntry getPreviousInAccessQueue(); + + public void setPreviousInAccessQueue(ReferenceEntry var1); + + public long getWriteTime(); + + public void setWriteTime(long var1); + + public ReferenceEntry getNextInWriteQueue(); + + public void setNextInWriteQueue(ReferenceEntry var1); + + public ReferenceEntry getPreviousInWriteQueue(); + + public void setPreviousInWriteQueue(ReferenceEntry var1); + } + + static interface ValueReference { + @Nullable + public V get(); + + public V waitForValue() throws ExecutionException; + + public int getWeight(); + + @Nullable + public ReferenceEntry getEntry(); + + public ValueReference copyFor(ReferenceQueue var1, @Nullable V var2, ReferenceEntry var3); + + public void notifyNewValue(@Nullable V var1); + + public boolean isLoading(); + + public boolean isActive(); + } + + static enum EntryFactory { + STRONG{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongEntry(key, hash, next); + } + } + , + STRONG_ACCESS{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongAccessEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyAccessEntry(original, newEntry); + return newEntry; + } + } + , + STRONG_WRITE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongWriteEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyWriteEntry(original, newEntry); + return newEntry; + } + } + , + STRONG_ACCESS_WRITE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongAccessWriteEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyAccessEntry(original, newEntry); + this.copyWriteEntry(original, newEntry); + return newEntry; + } + } + , + WEAK{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakEntry(segment.keyReferenceQueue, key, hash, next); + } + } + , + WEAK_ACCESS{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakAccessEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyAccessEntry(original, newEntry); + return newEntry; + } + } + , + WEAK_WRITE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakWriteEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyWriteEntry(original, newEntry); + return newEntry; + } + } + , + WEAK_ACCESS_WRITE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakAccessWriteEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyAccessEntry(original, newEntry); + this.copyWriteEntry(original, newEntry); + return newEntry; + } + }; + + static final int ACCESS_MASK = 1; + static final int WRITE_MASK = 2; + static final int WEAK_MASK = 4; + static final EntryFactory[] factories; + + static EntryFactory getFactory(Strength keyStrength, boolean usesAccessQueue, boolean usesWriteQueue) { + int flags = (keyStrength == Strength.WEAK ? 4 : 0) | (usesAccessQueue ? 1 : 0) | (usesWriteQueue ? 2 : 0); + return factories[flags]; + } + + abstract ReferenceEntry newEntry(Segment var1, K var2, int var3, @Nullable ReferenceEntry var4); + + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + return this.newEntry(segment, original.getKey(), original.getHash(), newNext); + } + + void copyAccessEntry(ReferenceEntry original, ReferenceEntry newEntry) { + newEntry.setAccessTime(original.getAccessTime()); + LocalCache.connectAccessOrder(original.getPreviousInAccessQueue(), newEntry); + LocalCache.connectAccessOrder(newEntry, original.getNextInAccessQueue()); + LocalCache.nullifyAccessOrder(original); + } + + void copyWriteEntry(ReferenceEntry original, ReferenceEntry newEntry) { + newEntry.setWriteTime(original.getWriteTime()); + LocalCache.connectWriteOrder(original.getPreviousInWriteQueue(), newEntry); + LocalCache.connectWriteOrder(newEntry, original.getNextInWriteQueue()); + LocalCache.nullifyWriteOrder(original); + } + + static { + factories = new EntryFactory[]{STRONG, STRONG_ACCESS, STRONG_WRITE, STRONG_ACCESS_WRITE, WEAK, WEAK_ACCESS, WEAK_WRITE, WEAK_ACCESS_WRITE}; + } + } + + static enum Strength { + STRONG{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value, int weight) { + return weight == 1 ? new StrongValueReference(value) : new WeightedStrongValueReference(value, weight); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.equals(); + } + } + , + SOFT{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value, int weight) { + return weight == 1 ? new SoftValueReference(segment.valueReferenceQueue, value, entry) : new WeightedSoftValueReference(segment.valueReferenceQueue, value, entry, weight); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.identity(); + } + } + , + WEAK{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value, int weight) { + return weight == 1 ? new WeakValueReference(segment.valueReferenceQueue, value, entry) : new WeightedWeakValueReference(segment.valueReferenceQueue, value, entry, weight); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.identity(); + } + }; + + + abstract ValueReference referenceValue(Segment var1, ReferenceEntry var2, V var3, int var4); + + abstract Equivalence defaultEquivalence(); + } +} diff --git a/src/com/google/common/cache/LongAddable.java b/src/com/google/common/cache/LongAddable.java new file mode 100644 index 0000000..8870c85 --- /dev/null +++ b/src/com/google/common/cache/LongAddable.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +interface LongAddable { + public void increment(); + + public void add(long var1); + + public long sum(); +} diff --git a/src/com/google/common/cache/LongAddables.java b/src/com/google/common/cache/LongAddables.java new file mode 100644 index 0000000..998fef6 --- /dev/null +++ b/src/com/google/common/cache/LongAddables.java @@ -0,0 +1,68 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Supplier; +import com.google.common.cache.LongAddable; +import com.google.common.cache.LongAdder; +import java.util.concurrent.atomic.AtomicLong; + +@GwtCompatible(emulated=true) +final class LongAddables { + private static final Supplier SUPPLIER; + + LongAddables() { + } + + public static LongAddable create() { + return SUPPLIER.get(); + } + + static { + Supplier supplier; + try { + new LongAdder(); + supplier = new Supplier(){ + + @Override + public LongAddable get() { + return new LongAdder(); + } + }; + } + catch (Throwable t) { + supplier = new Supplier(){ + + @Override + public LongAddable get() { + return new PureJavaLongAddable(); + } + }; + } + SUPPLIER = supplier; + } + + private static final class PureJavaLongAddable + extends AtomicLong + implements LongAddable { + private PureJavaLongAddable() { + } + + @Override + public void increment() { + this.getAndIncrement(); + } + + @Override + public void add(long x) { + this.getAndAdd(x); + } + + @Override + public long sum() { + return this.get(); + } + } +} diff --git a/src/com/google/common/cache/LongAdder.java b/src/com/google/common/cache/LongAdder.java new file mode 100644 index 0000000..fa93bd5 --- /dev/null +++ b/src/com/google/common/cache/LongAdder.java @@ -0,0 +1,117 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.cache.LongAddable; +import com.google.common.cache.Striped64; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +@GwtCompatible(emulated=true) +final class LongAdder +extends Striped64 +implements Serializable, +LongAddable { + private static final long serialVersionUID = 7249069246863182397L; + + @Override + final long fn(long v, long x) { + return v + x; + } + + @Override + public void add(long x) { + long b; + Striped64.Cell[] as = this.cells; + if (this.cells != null || !this.casBase(b = this.base, b + x)) { + long v; + Striped64.Cell a; + int n; + boolean uncontended = true; + int[] hc = (int[])threadHashCode.get(); + if (hc == null || as == null || (n = as.length) < 1 || (a = as[n - 1 & hc[0]]) == null || !(uncontended = a.cas(v = a.value, v + x))) { + this.retryUpdate(x, hc, uncontended); + } + } + } + + @Override + public void increment() { + this.add(1L); + } + + public void decrement() { + this.add(-1L); + } + + @Override + public long sum() { + long sum = this.base; + Striped64.Cell[] as = this.cells; + if (as != null) { + for (Striped64.Cell a : as) { + if (a == null) continue; + sum += a.value; + } + } + return sum; + } + + public void reset() { + this.internalReset(0L); + } + + public long sumThenReset() { + long sum = this.base; + Striped64.Cell[] as = this.cells; + this.base = 0L; + if (as != null) { + for (Striped64.Cell a : as) { + if (a == null) continue; + sum += a.value; + a.value = 0L; + } + } + return sum; + } + + public String toString() { + return Long.toString(this.sum()); + } + + @Override + public long longValue() { + return this.sum(); + } + + @Override + public int intValue() { + return (int)this.sum(); + } + + @Override + public float floatValue() { + return this.sum(); + } + + @Override + public double doubleValue() { + return this.sum(); + } + + private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); + s.writeLong(this.sum()); + } + + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + this.busy = 0; + this.cells = null; + this.base = s.readLong(); + } +} diff --git a/src/com/google/common/cache/RemovalCause.java b/src/com/google/common/cache/RemovalCause.java new file mode 100644 index 0000000..98992b6 --- /dev/null +++ b/src/com/google/common/cache/RemovalCause.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public enum RemovalCause { + EXPLICIT{ + + @Override + boolean wasEvicted() { + return false; + } + } + , + REPLACED{ + + @Override + boolean wasEvicted() { + return false; + } + } + , + COLLECTED{ + + @Override + boolean wasEvicted() { + return true; + } + } + , + EXPIRED{ + + @Override + boolean wasEvicted() { + return true; + } + } + , + SIZE{ + + @Override + boolean wasEvicted() { + return true; + } + }; + + + abstract boolean wasEvicted(); +} diff --git a/src/com/google/common/cache/RemovalListener.java b/src/com/google/common/cache/RemovalListener.java new file mode 100644 index 0000000..9678320 --- /dev/null +++ b/src/com/google/common/cache/RemovalListener.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.cache.RemovalNotification; + +@Beta +@GwtCompatible +public interface RemovalListener { + public void onRemoval(RemovalNotification var1); +} diff --git a/src/com/google/common/cache/RemovalListeners.java b/src/com/google/common/cache/RemovalListeners.java new file mode 100644 index 0000000..ff777b7 --- /dev/null +++ b/src/com/google/common/cache/RemovalListeners.java @@ -0,0 +1,34 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; +import java.util.concurrent.Executor; + +@Beta +public final class RemovalListeners { + private RemovalListeners() { + } + + public static RemovalListener asynchronous(final RemovalListener listener, final Executor executor) { + Preconditions.checkNotNull(listener); + Preconditions.checkNotNull(executor); + return new RemovalListener(){ + + @Override + public void onRemoval(final RemovalNotification notification) { + executor.execute(new Runnable(){ + + @Override + public void run() { + listener.onRemoval(notification); + } + }); + } + }; + } +} diff --git a/src/com/google/common/cache/RemovalNotification.java b/src/com/google/common/cache/RemovalNotification.java new file mode 100644 index 0000000..901ffce --- /dev/null +++ b/src/com/google/common/cache/RemovalNotification.java @@ -0,0 +1,77 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.cache.RemovalCause; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class RemovalNotification +implements Map.Entry { + @Nullable + private final K key; + @Nullable + private final V value; + private final RemovalCause cause; + private static final long serialVersionUID = 0L; + + RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) { + this.key = key; + this.value = value; + this.cause = Preconditions.checkNotNull(cause); + } + + public RemovalCause getCause() { + return this.cause; + } + + public boolean wasEvicted() { + return this.cause.wasEvicted(); + } + + @Override + @Nullable + public K getKey() { + return this.key; + } + + @Override + @Nullable + public V getValue() { + return this.value; + } + + @Override + public final V setValue(V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry that = (Map.Entry)object; + return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue()); + } + return false; + } + + @Override + public int hashCode() { + K k = this.getKey(); + V v = this.getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.getKey())); + String string2 = String.valueOf(String.valueOf(this.getValue())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append("=").append(string2).toString(); + } +} diff --git a/src/com/google/common/cache/Striped64.java b/src/com/google/common/cache/Striped64.java new file mode 100644 index 0000000..8ad45f0 --- /dev/null +++ b/src/com/google/common/cache/Striped64.java @@ -0,0 +1,224 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Random; +import sun.misc.Unsafe; + +abstract class Striped64 +extends Number { + static final ThreadLocal threadHashCode = new ThreadLocal(); + static final Random rng = new Random(); + static final int NCPU = Runtime.getRuntime().availableProcessors(); + volatile transient Cell[] cells; + volatile transient long base; + volatile transient int busy; + private static final Unsafe UNSAFE; + private static final long baseOffset; + private static final long busyOffset; + + Striped64() { + } + + final boolean casBase(long cmp, long val) { + return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val); + } + + final boolean casBusy() { + return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1); + } + + abstract long fn(long var1, long var3); + + /* + * WARNING - Removed try catching itself - possible behaviour change. + * Enabled force condition propagation + * Lifted jumps to return sites + */ + final void retryUpdate(long x, int[] hc, boolean wasUncontended) { + int h; + if (hc == null) { + hc = new int[1]; + threadHashCode.set(hc); + int r = rng.nextInt(); + hc[0] = r == 0 ? 1 : r; + h = hc[0]; + } else { + h = hc[0]; + } + boolean collide = false; + while (true) { + long v; + int n; + Cell[] as = this.cells; + if (this.cells != null && (n = as.length) > 0) { + Cell a = as[n - 1 & h]; + if (a == null) { + if (this.busy == 0) { + Cell r = new Cell(x); + if (this.busy == 0 && this.casBusy()) { + boolean created = false; + try { + int j; + int m; + Cell[] rs = this.cells; + if (this.cells != null && (m = rs.length) > 0 && rs[j = m - 1 & h] == null) { + rs[j] = r; + created = true; + } + } + finally { + this.busy = 0; + } + if (!created) continue; + return; + } + } + collide = false; + } else if (!wasUncontended) { + wasUncontended = true; + } else { + v = a.value; + if (a.cas(v, this.fn(v, x))) return; + if (n >= NCPU || this.cells != as) { + collide = false; + } else if (!collide) { + collide = true; + } else if (this.busy == 0 && this.casBusy()) { + try { + if (this.cells == as) { + Cell[] rs = new Cell[n << 1]; + for (int i = 0; i < n; ++i) { + rs[i] = as[i]; + } + this.cells = rs; + } + } + finally { + this.busy = 0; + } + collide = false; + continue; + } + } + h ^= h << 13; + h ^= h >>> 17; + h ^= h << 5; + hc[0] = h; + continue; + } + if (this.busy == 0 && this.cells == as && this.casBusy()) { + boolean init = false; + try { + if (this.cells == as) { + Cell[] rs = new Cell[2]; + rs[h & 1] = new Cell(x); + this.cells = rs; + init = true; + } + } + finally { + this.busy = 0; + } + if (!init) continue; + return; + } + v = this.base; + if (this.casBase(v, this.fn(v, x))) return; + } + } + + final void internalReset(long initialValue) { + Cell[] as = this.cells; + this.base = initialValue; + if (as != null) { + for (Cell a : as) { + if (a == null) continue; + a.value = initialValue; + } + } + } + + private static Unsafe getUnsafe() { + try { + return Unsafe.getUnsafe(); + } + catch (SecurityException tryReflectionInstead) { + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction(){ + + @Override + public Unsafe run() throws Exception { + Class k = Unsafe.class; + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (!k.isInstance(x)) continue; + return (Unsafe)k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + } + }); + } + catch (PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", e.getCause()); + } + } + } + + static { + try { + UNSAFE = Striped64.getUnsafe(); + Class sk = Striped64.class; + baseOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("base")); + busyOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("busy")); + } + catch (Exception e) { + throw new Error(e); + } + } + + static final class Cell { + volatile long p0; + volatile long p1; + volatile long p2; + volatile long p3; + volatile long p4; + volatile long p5; + volatile long p6; + volatile long value; + volatile long q0; + volatile long q1; + volatile long q2; + volatile long q3; + volatile long q4; + volatile long q5; + volatile long q6; + private static final Unsafe UNSAFE; + private static final long valueOffset; + + Cell(long x) { + this.value = x; + } + + final boolean cas(long cmp, long val) { + return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val); + } + + static { + try { + UNSAFE = Striped64.getUnsafe(); + Class ak = Cell.class; + valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value")); + } + catch (Exception e) { + throw new Error(e); + } + } + } +} diff --git a/src/com/google/common/cache/Weigher.java b/src/com/google/common/cache/Weigher.java new file mode 100644 index 0000000..397a3d7 --- /dev/null +++ b/src/com/google/common/cache/Weigher.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public interface Weigher { + public int weigh(K var1, V var2); +} diff --git a/src/com/google/common/cache/package-info.java b/src/com/google/common/cache/package-info.java new file mode 100644 index 0000000..98e3b2a --- /dev/null +++ b/src/com/google/common/cache/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.cache; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/collect/AbstractBiMap.java b/src/com/google/common/collect/AbstractBiMap.java new file mode 100644 index 0000000..b52343c --- /dev/null +++ b/src/com/google/common/collect/AbstractBiMap.java @@ -0,0 +1,382 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.Maps; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +abstract class AbstractBiMap +extends ForwardingMap +implements BiMap, +Serializable { + private transient Map delegate; + transient AbstractBiMap inverse; + private transient Set keySet; + private transient Set valueSet; + private transient Set> entrySet; + @GwtIncompatible(value="Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + AbstractBiMap(Map forward, Map backward) { + this.setDelegates(forward, backward); + } + + private AbstractBiMap(Map backward, AbstractBiMap forward) { + this.delegate = backward; + this.inverse = forward; + } + + @Override + protected Map delegate() { + return this.delegate; + } + + K checkKey(@Nullable K key) { + return key; + } + + V checkValue(@Nullable V value) { + return value; + } + + void setDelegates(Map forward, Map backward) { + Preconditions.checkState(this.delegate == null); + Preconditions.checkState(this.inverse == null); + Preconditions.checkArgument(forward.isEmpty()); + Preconditions.checkArgument(backward.isEmpty()); + Preconditions.checkArgument(forward != backward); + this.delegate = forward; + this.inverse = new Inverse(backward, this); + } + + void setInverse(AbstractBiMap inverse) { + this.inverse = inverse; + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.inverse.containsKey(value); + } + + @Override + public V put(@Nullable K key, @Nullable V value) { + return this.putInBothMaps(key, value, false); + } + + @Override + public V forcePut(@Nullable K key, @Nullable V value) { + return this.putInBothMaps(key, value, true); + } + + private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) { + this.checkKey(key); + this.checkValue(value); + boolean containedKey = this.containsKey(key); + if (containedKey && Objects.equal(value, this.get(key))) { + return value; + } + if (force) { + this.inverse().remove(value); + } else { + Preconditions.checkArgument(!this.containsValue(value), "value already present: %s", value); + } + V oldValue = this.delegate.put(key, value); + this.updateInverseMap(key, containedKey, oldValue, value); + return oldValue; + } + + private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) { + if (containedKey) { + this.removeFromInverseMap(oldValue); + } + this.inverse.delegate.put(newValue, key); + } + + @Override + public V remove(@Nullable Object key) { + return this.containsKey(key) ? (V)this.removeFromBothMaps(key) : null; + } + + private V removeFromBothMaps(Object key) { + V oldValue = this.delegate.remove(key); + this.removeFromInverseMap(oldValue); + return oldValue; + } + + private void removeFromInverseMap(V oldValue) { + this.inverse.delegate.remove(oldValue); + } + + @Override + public void putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void clear() { + this.delegate.clear(); + this.inverse.delegate.clear(); + } + + @Override + public BiMap inverse() { + return this.inverse; + } + + @Override + public Set keySet() { + KeySet result = this.keySet; + return result == null ? (this.keySet = new KeySet()) : result; + } + + @Override + public Set values() { + ValueSet result = this.valueSet; + return result == null ? (this.valueSet = new ValueSet()) : result; + } + + @Override + public Set> entrySet() { + EntrySet result = this.entrySet; + return result == null ? (this.entrySet = new EntrySet()) : result; + } + + private static class Inverse + extends AbstractBiMap { + @GwtIncompatible(value="Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + private Inverse(Map backward, AbstractBiMap forward) { + super(backward, forward); + } + + @Override + K checkKey(K key) { + return this.inverse.checkValue(key); + } + + @Override + V checkValue(V value) { + return this.inverse.checkKey(value); + } + + @GwtIncompatible(value="java.io.ObjectOuputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.inverse()); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.setInverse((AbstractBiMap)stream.readObject()); + } + + @GwtIncompatible(value="Not needed in the emulated source.") + Object readResolve() { + return this.inverse().inverse(); + } + } + + private class EntrySet + extends ForwardingSet> { + final Set> esDelegate; + + private EntrySet() { + this.esDelegate = AbstractBiMap.this.delegate.entrySet(); + } + + @Override + protected Set> delegate() { + return this.esDelegate; + } + + @Override + public void clear() { + AbstractBiMap.this.clear(); + } + + @Override + public boolean remove(Object object) { + if (!this.esDelegate.contains(object)) { + return false; + } + Map.Entry entry = (Map.Entry)object; + AbstractBiMap.this.inverse.delegate.remove(entry.getValue()); + this.esDelegate.remove(entry); + return true; + } + + @Override + public Iterator> iterator() { + final Iterator iterator = this.esDelegate.iterator(); + return new Iterator>(){ + Map.Entry entry; + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Map.Entry next() { + this.entry = (Map.Entry)iterator.next(); + final Map.Entry finalEntry = this.entry; + return new ForwardingMapEntry(){ + + @Override + protected Map.Entry delegate() { + return finalEntry; + } + + @Override + public V setValue(V value) { + Preconditions.checkState(EntrySet.this.contains(this), "entry no longer in map"); + if (Objects.equal(value, this.getValue())) { + return value; + } + Preconditions.checkArgument(!AbstractBiMap.this.containsValue(value), "value already present: %s", value); + Object oldValue = finalEntry.setValue(value); + Preconditions.checkState(Objects.equal(value, AbstractBiMap.this.get(this.getKey())), "entry no longer in map"); + AbstractBiMap.this.updateInverseMap(this.getKey(), true, oldValue, value); + return oldValue; + } + }; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.entry != null); + Object value = this.entry.getValue(); + iterator.remove(); + AbstractBiMap.this.removeFromInverseMap(value); + } + }; + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public boolean contains(Object o) { + return Maps.containsEntryImpl(this.delegate(), o); + } + + @Override + public boolean containsAll(Collection c) { + return this.standardContainsAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return this.standardRemoveAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return this.standardRetainAll(c); + } + } + + private class ValueSet + extends ForwardingSet { + final Set valuesDelegate; + + private ValueSet() { + this.valuesDelegate = AbstractBiMap.this.inverse.keySet(); + } + + @Override + protected Set delegate() { + return this.valuesDelegate; + } + + @Override + public Iterator iterator() { + return Maps.valueIterator(AbstractBiMap.this.entrySet().iterator()); + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public String toString() { + return this.standardToString(); + } + } + + private class KeySet + extends ForwardingSet { + private KeySet() { + } + + @Override + protected Set delegate() { + return AbstractBiMap.this.delegate.keySet(); + } + + @Override + public void clear() { + AbstractBiMap.this.clear(); + } + + @Override + public boolean remove(Object key) { + if (!this.contains(key)) { + return false; + } + AbstractBiMap.this.removeFromBothMaps(key); + return true; + } + + @Override + public boolean removeAll(Collection keysToRemove) { + return this.standardRemoveAll(keysToRemove); + } + + @Override + public boolean retainAll(Collection keysToRetain) { + return this.standardRetainAll(keysToRetain); + } + + @Override + public Iterator iterator() { + return Maps.keyIterator(AbstractBiMap.this.entrySet().iterator()); + } + } +} diff --git a/src/com/google/common/collect/AbstractIndexedListIterator.java b/src/com/google/common/collect/AbstractIndexedListIterator.java new file mode 100644 index 0000000..975ecc0 --- /dev/null +++ b/src/com/google/common/collect/AbstractIndexedListIterator.java @@ -0,0 +1,64 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.UnmodifiableListIterator; +import java.util.NoSuchElementException; + +@GwtCompatible +abstract class AbstractIndexedListIterator +extends UnmodifiableListIterator { + private final int size; + private int position; + + protected abstract E get(int var1); + + protected AbstractIndexedListIterator(int size) { + this(size, 0); + } + + protected AbstractIndexedListIterator(int size, int position) { + Preconditions.checkPositionIndex(position, size); + this.size = size; + this.position = position; + } + + @Override + public final boolean hasNext() { + return this.position < this.size; + } + + @Override + public final E next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + return this.get(this.position++); + } + + @Override + public final int nextIndex() { + return this.position; + } + + @Override + public final boolean hasPrevious() { + return this.position > 0; + } + + @Override + public final E previous() { + if (!this.hasPrevious()) { + throw new NoSuchElementException(); + } + return this.get(--this.position); + } + + @Override + public final int previousIndex() { + return this.position - 1; + } +} diff --git a/src/com/google/common/collect/AbstractIterator.java b/src/com/google/common/collect/AbstractIterator.java new file mode 100644 index 0000000..961b64c --- /dev/null +++ b/src/com/google/common/collect/AbstractIterator.java @@ -0,0 +1,76 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.UnmodifiableIterator; +import java.util.NoSuchElementException; + +@GwtCompatible +public abstract class AbstractIterator +extends UnmodifiableIterator { + private State state = State.NOT_READY; + private T next; + + protected AbstractIterator() { + } + + protected abstract T computeNext(); + + protected final T endOfData() { + this.state = State.DONE; + return null; + } + + @Override + public final boolean hasNext() { + Preconditions.checkState(this.state != State.FAILED); + switch (this.state) { + case DONE: { + return false; + } + case READY: { + return true; + } + } + return this.tryToComputeNext(); + } + + private boolean tryToComputeNext() { + this.state = State.FAILED; + this.next = this.computeNext(); + if (this.state != State.DONE) { + this.state = State.READY; + return true; + } + return false; + } + + @Override + public final T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.state = State.NOT_READY; + T result = this.next; + this.next = null; + return result; + } + + public final T peek() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + return this.next; + } + + private static enum State { + READY, + NOT_READY, + DONE, + FAILED; + + } +} diff --git a/src/com/google/common/collect/AbstractListMultimap.java b/src/com/google/common/collect/AbstractListMultimap.java new file mode 100644 index 0000000..ae609db --- /dev/null +++ b/src/com/google/common/collect/AbstractListMultimap.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ListMultimap; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractListMultimap +extends AbstractMapBasedMultimap +implements ListMultimap { + private static final long serialVersionUID = 6588350623831699109L; + + protected AbstractListMultimap(Map> map) { + super(map); + } + + @Override + abstract List createCollection(); + + @Override + List createUnmodifiableEmptyCollection() { + return ImmutableList.of(); + } + + @Override + public List get(@Nullable K key) { + return (List)super.get(key); + } + + @Override + public List removeAll(@Nullable Object key) { + return (List)super.removeAll(key); + } + + @Override + public List replaceValues(@Nullable K key, Iterable values) { + return (List)super.replaceValues(key, values); + } + + @Override + public boolean put(@Nullable K key, @Nullable V value) { + return super.put(key, value); + } + + @Override + public Map> asMap() { + return super.asMap(); + } + + @Override + public boolean equals(@Nullable Object object) { + return super.equals(object); + } +} diff --git a/src/com/google/common/collect/AbstractMapBasedMultimap.java b/src/com/google/common/collect/AbstractMapBasedMultimap.java new file mode 100644 index 0000000..7497d0a --- /dev/null +++ b/src/com/google/common/collect/AbstractMapBasedMultimap.java @@ -0,0 +1,1336 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +abstract class AbstractMapBasedMultimap +extends AbstractMultimap +implements Serializable { + private transient Map> map; + private transient int totalSize; + private static final long serialVersionUID = 2447537837011683357L; + + protected AbstractMapBasedMultimap(Map> map) { + Preconditions.checkArgument(map.isEmpty()); + this.map = map; + } + + final void setMap(Map> map) { + this.map = map; + this.totalSize = 0; + for (Collection> values : map.values()) { + Preconditions.checkArgument(!values.isEmpty()); + this.totalSize += values.size(); + } + } + + Collection createUnmodifiableEmptyCollection() { + return this.unmodifiableCollectionSubclass(this.createCollection()); + } + + abstract Collection createCollection(); + + Collection createCollection(@Nullable K key) { + return this.createCollection(); + } + + Map> backingMap() { + return this.map; + } + + @Override + public int size() { + return this.totalSize; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.map.containsKey(key); + } + + @Override + public boolean put(@Nullable K key, @Nullable V value) { + Collection collection = this.map.get(key); + if (collection == null) { + collection = this.createCollection(key); + if (collection.add(value)) { + ++this.totalSize; + this.map.put(key, collection); + return true; + } + throw new AssertionError((Object)"New Collection violated the Collection spec"); + } + if (collection.add(value)) { + ++this.totalSize; + return true; + } + return false; + } + + private Collection getOrCreateCollection(@Nullable K key) { + Collection collection = this.map.get(key); + if (collection == null) { + collection = this.createCollection(key); + this.map.put(key, collection); + } + return collection; + } + + @Override + public Collection replaceValues(@Nullable K key, Iterable values) { + Iterator iterator = values.iterator(); + if (!iterator.hasNext()) { + return this.removeAll(key); + } + Collection collection = this.getOrCreateCollection(key); + Collection oldValues = this.createCollection(); + oldValues.addAll(collection); + this.totalSize -= collection.size(); + collection.clear(); + while (iterator.hasNext()) { + if (!collection.add(iterator.next())) continue; + ++this.totalSize; + } + return this.unmodifiableCollectionSubclass(oldValues); + } + + @Override + public Collection removeAll(@Nullable Object key) { + Collection collection = this.map.remove(key); + if (collection == null) { + return this.createUnmodifiableEmptyCollection(); + } + Collection output = this.createCollection(); + output.addAll(collection); + this.totalSize -= collection.size(); + collection.clear(); + return this.unmodifiableCollectionSubclass(output); + } + + Collection unmodifiableCollectionSubclass(Collection collection) { + if (collection instanceof SortedSet) { + return Collections.unmodifiableSortedSet((SortedSet)collection); + } + if (collection instanceof Set) { + return Collections.unmodifiableSet((Set)collection); + } + if (collection instanceof List) { + return Collections.unmodifiableList((List)collection); + } + return Collections.unmodifiableCollection(collection); + } + + @Override + public void clear() { + for (Collection collection : this.map.values()) { + collection.clear(); + } + this.map.clear(); + this.totalSize = 0; + } + + @Override + public Collection get(@Nullable K key) { + Collection collection = this.map.get(key); + if (collection == null) { + collection = this.createCollection(key); + } + return this.wrapCollection(key, collection); + } + + Collection wrapCollection(@Nullable K key, Collection collection) { + if (collection instanceof SortedSet) { + return new WrappedSortedSet(key, (SortedSet)collection, null); + } + if (collection instanceof Set) { + return new WrappedSet(key, (Set)collection); + } + if (collection instanceof List) { + return this.wrapList(key, (List)collection, null); + } + return new WrappedCollection(key, collection, null); + } + + private List wrapList(@Nullable K key, List list, @Nullable WrappedCollection ancestor) { + return list instanceof RandomAccess ? new RandomAccessWrappedList(key, list, ancestor) : new WrappedList(key, list, ancestor); + } + + private Iterator iteratorOrListIterator(Collection collection) { + return collection instanceof List ? ((List)collection).listIterator() : collection.iterator(); + } + + @Override + Set createKeySet() { + return this.map instanceof SortedMap ? new SortedKeySet((SortedMap)this.map) : new KeySet(this.map); + } + + private int removeValuesForKey(Object key) { + Collection collection = Maps.safeRemove(this.map, key); + int count = 0; + if (collection != null) { + count = collection.size(); + collection.clear(); + this.totalSize -= count; + } + return count; + } + + @Override + public Collection values() { + return super.values(); + } + + @Override + Iterator valueIterator() { + return new Itr(){ + + @Override + V output(K key, V value) { + return value; + } + }; + } + + @Override + public Collection> entries() { + return super.entries(); + } + + @Override + Iterator> entryIterator() { + return new Itr>(){ + + @Override + Map.Entry output(K key, V value) { + return Maps.immutableEntry(key, value); + } + }; + } + + @Override + Map> createAsMap() { + return this.map instanceof SortedMap ? new SortedAsMap((SortedMap)this.map) : new AsMap(this.map); + } + + @GwtIncompatible(value="NavigableAsMap") + class NavigableAsMap + extends SortedAsMap + implements NavigableMap> { + NavigableAsMap(NavigableMap> submap) { + super(submap); + } + + NavigableMap> sortedMap() { + return (NavigableMap)super.sortedMap(); + } + + @Override + public Map.Entry> lowerEntry(K key) { + Map.Entry entry = this.sortedMap().lowerEntry(key); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public K lowerKey(K key) { + return this.sortedMap().lowerKey(key); + } + + @Override + public Map.Entry> floorEntry(K key) { + Map.Entry entry = this.sortedMap().floorEntry(key); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public K floorKey(K key) { + return this.sortedMap().floorKey(key); + } + + @Override + public Map.Entry> ceilingEntry(K key) { + Map.Entry entry = this.sortedMap().ceilingEntry(key); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public K ceilingKey(K key) { + return this.sortedMap().ceilingKey(key); + } + + @Override + public Map.Entry> higherEntry(K key) { + Map.Entry entry = this.sortedMap().higherEntry(key); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public K higherKey(K key) { + return this.sortedMap().higherKey(key); + } + + @Override + public Map.Entry> firstEntry() { + Map.Entry entry = this.sortedMap().firstEntry(); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public Map.Entry> lastEntry() { + Map.Entry entry = this.sortedMap().lastEntry(); + return entry == null ? null : this.wrapEntry(entry); + } + + @Override + public Map.Entry> pollFirstEntry() { + return this.pollAsMapEntry(this.entrySet().iterator()); + } + + @Override + public Map.Entry> pollLastEntry() { + return this.pollAsMapEntry(this.descendingMap().entrySet().iterator()); + } + + Map.Entry> pollAsMapEntry(Iterator>> entryIterator) { + if (!entryIterator.hasNext()) { + return null; + } + Map.Entry entry = entryIterator.next(); + Collection output = AbstractMapBasedMultimap.this.createCollection(); + output.addAll(entry.getValue()); + entryIterator.remove(); + return Maps.immutableEntry(entry.getKey(), AbstractMapBasedMultimap.this.unmodifiableCollectionSubclass(output)); + } + + @Override + public NavigableMap> descendingMap() { + return new NavigableAsMap(this.sortedMap().descendingMap()); + } + + @Override + public NavigableSet keySet() { + return (NavigableSet)super.keySet(); + } + + @Override + NavigableSet createKeySet() { + return new NavigableKeySet(this.sortedMap()); + } + + @Override + public NavigableSet navigableKeySet() { + return this.keySet(); + } + + @Override + public NavigableSet descendingKeySet() { + return this.descendingMap().navigableKeySet(); + } + + @Override + public NavigableMap> subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public NavigableMap> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return new NavigableAsMap(this.sortedMap().subMap(fromKey, fromInclusive, toKey, toInclusive)); + } + + @Override + public NavigableMap> headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public NavigableMap> headMap(K toKey, boolean inclusive) { + return new NavigableAsMap(this.sortedMap().headMap(toKey, inclusive)); + } + + @Override + public NavigableMap> tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Override + public NavigableMap> tailMap(K fromKey, boolean inclusive) { + return new NavigableAsMap(this.sortedMap().tailMap(fromKey, inclusive)); + } + } + + private class SortedAsMap + extends AsMap + implements SortedMap> { + SortedSet sortedKeySet; + + SortedAsMap(SortedMap> submap) { + super(submap); + } + + SortedMap> sortedMap() { + return (SortedMap)this.submap; + } + + @Override + public Comparator comparator() { + return this.sortedMap().comparator(); + } + + @Override + public K firstKey() { + return this.sortedMap().firstKey(); + } + + @Override + public K lastKey() { + return this.sortedMap().lastKey(); + } + + @Override + public SortedMap> headMap(K toKey) { + return new SortedAsMap(this.sortedMap().headMap(toKey)); + } + + @Override + public SortedMap> subMap(K fromKey, K toKey) { + return new SortedAsMap(this.sortedMap().subMap(fromKey, toKey)); + } + + @Override + public SortedMap> tailMap(K fromKey) { + return new SortedAsMap(this.sortedMap().tailMap(fromKey)); + } + + @Override + public SortedSet keySet() { + SortedSet result = this.sortedKeySet; + return result == null ? (this.sortedKeySet = this.createKeySet()) : result; + } + + @Override + SortedSet createKeySet() { + return new SortedKeySet(this.sortedMap()); + } + } + + private class AsMap + extends Maps.ImprovedAbstractMap> { + final transient Map> submap; + + AsMap(Map> submap) { + this.submap = submap; + } + + @Override + protected Set>> createEntrySet() { + return new AsMapEntries(); + } + + @Override + public boolean containsKey(Object key) { + return Maps.safeContainsKey(this.submap, key); + } + + @Override + public Collection get(Object key) { + Collection collection = Maps.safeGet(this.submap, key); + if (collection == null) { + return null; + } + Object k = key; + return AbstractMapBasedMultimap.this.wrapCollection(k, collection); + } + + @Override + public Set keySet() { + return AbstractMapBasedMultimap.this.keySet(); + } + + @Override + public int size() { + return this.submap.size(); + } + + @Override + public Collection remove(Object key) { + Collection collection = this.submap.remove(key); + if (collection == null) { + return null; + } + Collection output = AbstractMapBasedMultimap.this.createCollection(); + output.addAll(collection); + AbstractMapBasedMultimap.this.totalSize -= collection.size(); + collection.clear(); + return output; + } + + @Override + public boolean equals(@Nullable Object object) { + return this == object || this.submap.equals(object); + } + + @Override + public int hashCode() { + return this.submap.hashCode(); + } + + @Override + public String toString() { + return this.submap.toString(); + } + + @Override + public void clear() { + if (this.submap == AbstractMapBasedMultimap.this.map) { + AbstractMapBasedMultimap.this.clear(); + } else { + Iterators.clear(new AsMapIterator()); + } + } + + Map.Entry> wrapEntry(Map.Entry> entry) { + Object key = entry.getKey(); + return Maps.immutableEntry(key, AbstractMapBasedMultimap.this.wrapCollection(key, entry.getValue())); + } + + class AsMapIterator + implements Iterator>> { + final Iterator>> delegateIterator; + Collection collection; + + AsMapIterator() { + this.delegateIterator = AsMap.this.submap.entrySet().iterator(); + } + + @Override + public boolean hasNext() { + return this.delegateIterator.hasNext(); + } + + @Override + public Map.Entry> next() { + Map.Entry entry = this.delegateIterator.next(); + this.collection = entry.getValue(); + return AsMap.this.wrapEntry(entry); + } + + @Override + public void remove() { + this.delegateIterator.remove(); + AbstractMapBasedMultimap.this.totalSize -= this.collection.size(); + this.collection.clear(); + } + } + + class AsMapEntries + extends Maps.EntrySet> { + AsMapEntries() { + } + + @Override + Map> map() { + return AsMap.this; + } + + @Override + public Iterator>> iterator() { + return new AsMapIterator(); + } + + @Override + public boolean contains(Object o) { + return Collections2.safeContains(AsMap.this.submap.entrySet(), o); + } + + @Override + public boolean remove(Object o) { + if (!this.contains(o)) { + return false; + } + Map.Entry entry = (Map.Entry)o; + AbstractMapBasedMultimap.this.removeValuesForKey(entry.getKey()); + return true; + } + } + } + + private abstract class Itr + implements Iterator { + final Iterator>> keyIterator; + K key; + Collection collection; + Iterator valueIterator; + + Itr() { + this.keyIterator = AbstractMapBasedMultimap.this.map.entrySet().iterator(); + this.key = null; + this.collection = null; + this.valueIterator = Iterators.emptyModifiableIterator(); + } + + abstract T output(K var1, V var2); + + @Override + public boolean hasNext() { + return this.keyIterator.hasNext() || this.valueIterator.hasNext(); + } + + @Override + public T next() { + if (!this.valueIterator.hasNext()) { + Map.Entry mapEntry = this.keyIterator.next(); + this.key = mapEntry.getKey(); + this.collection = mapEntry.getValue(); + this.valueIterator = this.collection.iterator(); + } + return this.output(this.key, this.valueIterator.next()); + } + + @Override + public void remove() { + this.valueIterator.remove(); + if (this.collection.isEmpty()) { + this.keyIterator.remove(); + } + AbstractMapBasedMultimap.this.totalSize--; + } + } + + @GwtIncompatible(value="NavigableSet") + class NavigableKeySet + extends SortedKeySet + implements NavigableSet { + NavigableKeySet(NavigableMap> subMap) { + super(subMap); + } + + NavigableMap> sortedMap() { + return (NavigableMap)super.sortedMap(); + } + + @Override + public K lower(K k) { + return this.sortedMap().lowerKey(k); + } + + @Override + public K floor(K k) { + return this.sortedMap().floorKey(k); + } + + @Override + public K ceiling(K k) { + return this.sortedMap().ceilingKey(k); + } + + @Override + public K higher(K k) { + return this.sortedMap().higherKey(k); + } + + @Override + public K pollFirst() { + return Iterators.pollNext(this.iterator()); + } + + @Override + public K pollLast() { + return Iterators.pollNext(this.descendingIterator()); + } + + @Override + public NavigableSet descendingSet() { + return new NavigableKeySet(this.sortedMap().descendingMap()); + } + + @Override + public Iterator descendingIterator() { + return this.descendingSet().iterator(); + } + + @Override + public NavigableSet headSet(K toElement) { + return this.headSet((K)toElement, false); + } + + @Override + public NavigableSet headSet(K toElement, boolean inclusive) { + return new NavigableKeySet(this.sortedMap().headMap(toElement, inclusive)); + } + + @Override + public NavigableSet subSet(K fromElement, K toElement) { + return this.subSet((K)fromElement, true, (K)toElement, false); + } + + @Override + public NavigableSet subSet(K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) { + return new NavigableKeySet(this.sortedMap().subMap(fromElement, fromInclusive, toElement, toInclusive)); + } + + @Override + public NavigableSet tailSet(K fromElement) { + return this.tailSet((K)fromElement, true); + } + + @Override + public NavigableSet tailSet(K fromElement, boolean inclusive) { + return new NavigableKeySet(this.sortedMap().tailMap(fromElement, inclusive)); + } + } + + private class SortedKeySet + extends KeySet + implements SortedSet { + SortedKeySet(SortedMap> subMap) { + super(subMap); + } + + SortedMap> sortedMap() { + return (SortedMap)super.map(); + } + + @Override + public Comparator comparator() { + return this.sortedMap().comparator(); + } + + @Override + public K first() { + return this.sortedMap().firstKey(); + } + + @Override + public SortedSet headSet(K toElement) { + return new SortedKeySet(this.sortedMap().headMap(toElement)); + } + + @Override + public K last() { + return this.sortedMap().lastKey(); + } + + @Override + public SortedSet subSet(K fromElement, K toElement) { + return new SortedKeySet(this.sortedMap().subMap(fromElement, toElement)); + } + + @Override + public SortedSet tailSet(K fromElement) { + return new SortedKeySet(this.sortedMap().tailMap(fromElement)); + } + } + + private class KeySet + extends Maps.KeySet> { + KeySet(Map> subMap) { + super(subMap); + } + + @Override + public Iterator iterator() { + final Iterator entryIterator = this.map().entrySet().iterator(); + return new Iterator(){ + Map.Entry> entry; + + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public K next() { + this.entry = (Map.Entry)entryIterator.next(); + return this.entry.getKey(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.entry != null); + Collection collection = this.entry.getValue(); + entryIterator.remove(); + AbstractMapBasedMultimap.this.totalSize -= collection.size(); + collection.clear(); + } + }; + } + + @Override + public boolean remove(Object key) { + int count = 0; + Collection collection = (Collection)this.map().remove(key); + if (collection != null) { + count = collection.size(); + collection.clear(); + AbstractMapBasedMultimap.this.totalSize -= count; + } + return count > 0; + } + + @Override + public void clear() { + Iterators.clear(this.iterator()); + } + + @Override + public boolean containsAll(Collection c) { + return this.map().keySet().containsAll(c); + } + + @Override + public boolean equals(@Nullable Object object) { + return this == object || this.map().keySet().equals(object); + } + + @Override + public int hashCode() { + return this.map().keySet().hashCode(); + } + } + + private class RandomAccessWrappedList + extends WrappedList + implements RandomAccess { + RandomAccessWrappedList(K key, @Nullable List delegate, WrappedCollection ancestor) { + super(key, delegate, ancestor); + } + } + + private class WrappedList + extends WrappedCollection + implements List { + WrappedList(K key, @Nullable List delegate, WrappedCollection ancestor) { + super(key, delegate, ancestor); + } + + List getListDelegate() { + return (List)this.getDelegate(); + } + + @Override + public boolean addAll(int index, Collection c) { + if (c.isEmpty()) { + return false; + } + int oldSize = this.size(); + boolean changed = this.getListDelegate().addAll(index, c); + if (changed) { + int newSize = this.getDelegate().size(); + AbstractMapBasedMultimap.this.totalSize += newSize - oldSize; + if (oldSize == 0) { + this.addToMap(); + } + } + return changed; + } + + @Override + public V get(int index) { + this.refreshIfEmpty(); + return this.getListDelegate().get(index); + } + + @Override + public V set(int index, V element) { + this.refreshIfEmpty(); + return this.getListDelegate().set(index, element); + } + + @Override + public void add(int index, V element) { + this.refreshIfEmpty(); + boolean wasEmpty = this.getDelegate().isEmpty(); + this.getListDelegate().add(index, element); + AbstractMapBasedMultimap.this.totalSize++; + if (wasEmpty) { + this.addToMap(); + } + } + + @Override + public V remove(int index) { + this.refreshIfEmpty(); + Object value = this.getListDelegate().remove(index); + AbstractMapBasedMultimap.this.totalSize--; + this.removeIfEmpty(); + return value; + } + + @Override + public int indexOf(Object o) { + this.refreshIfEmpty(); + return this.getListDelegate().indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + this.refreshIfEmpty(); + return this.getListDelegate().lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + this.refreshIfEmpty(); + return new WrappedListIterator(); + } + + @Override + public ListIterator listIterator(int index) { + this.refreshIfEmpty(); + return new WrappedListIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + this.refreshIfEmpty(); + return AbstractMapBasedMultimap.this.wrapList(this.getKey(), this.getListDelegate().subList(fromIndex, toIndex), this.getAncestor() == null ? this : this.getAncestor()); + } + + /* + * Signature claims super is com.google.common.collect.AbstractMapBasedMultimap$WrappedCollection.WrappedIterator, not com.google.common.collect.AbstractMapBasedMultimap$WrappedCollection$WrappedIterator - discarding signature. + */ + private class WrappedListIterator + extends WrappedCollection.WrappedIterator + implements ListIterator { + WrappedListIterator() { + } + + public WrappedListIterator(int index) { + super(WrappedList.this.getListDelegate().listIterator(index)); + } + + private ListIterator getDelegateListIterator() { + return (ListIterator)this.getDelegateIterator(); + } + + @Override + public boolean hasPrevious() { + return this.getDelegateListIterator().hasPrevious(); + } + + public V previous() { + return this.getDelegateListIterator().previous(); + } + + @Override + public int nextIndex() { + return this.getDelegateListIterator().nextIndex(); + } + + @Override + public int previousIndex() { + return this.getDelegateListIterator().previousIndex(); + } + + public void set(V value) { + this.getDelegateListIterator().set(value); + } + + public void add(V value) { + boolean wasEmpty = WrappedList.this.isEmpty(); + this.getDelegateListIterator().add(value); + AbstractMapBasedMultimap.this.totalSize++; + if (wasEmpty) { + WrappedList.this.addToMap(); + } + } + } + } + + @GwtIncompatible(value="NavigableSet") + class WrappedNavigableSet + extends WrappedSortedSet + implements NavigableSet { + WrappedNavigableSet(K key, @Nullable NavigableSet delegate, WrappedCollection ancestor) { + super(key, delegate, ancestor); + } + + NavigableSet getSortedSetDelegate() { + return (NavigableSet)super.getSortedSetDelegate(); + } + + @Override + public V lower(V v) { + return this.getSortedSetDelegate().lower(v); + } + + @Override + public V floor(V v) { + return this.getSortedSetDelegate().floor(v); + } + + @Override + public V ceiling(V v) { + return this.getSortedSetDelegate().ceiling(v); + } + + @Override + public V higher(V v) { + return this.getSortedSetDelegate().higher(v); + } + + @Override + public V pollFirst() { + return Iterators.pollNext(this.iterator()); + } + + @Override + public V pollLast() { + return Iterators.pollNext(this.descendingIterator()); + } + + private NavigableSet wrap(NavigableSet wrapped) { + return new WrappedNavigableSet(this.key, wrapped, this.getAncestor() == null ? this : this.getAncestor()); + } + + @Override + public NavigableSet descendingSet() { + return this.wrap(this.getSortedSetDelegate().descendingSet()); + } + + @Override + public Iterator descendingIterator() { + return new WrappedCollection.WrappedIterator(this.getSortedSetDelegate().descendingIterator()); + } + + @Override + public NavigableSet subSet(V fromElement, boolean fromInclusive, V toElement, boolean toInclusive) { + return this.wrap(this.getSortedSetDelegate().subSet(fromElement, fromInclusive, toElement, toInclusive)); + } + + @Override + public NavigableSet headSet(V toElement, boolean inclusive) { + return this.wrap(this.getSortedSetDelegate().headSet(toElement, inclusive)); + } + + @Override + public NavigableSet tailSet(V fromElement, boolean inclusive) { + return this.wrap(this.getSortedSetDelegate().tailSet(fromElement, inclusive)); + } + } + + private class WrappedSortedSet + extends WrappedCollection + implements SortedSet { + WrappedSortedSet(K key, @Nullable SortedSet delegate, WrappedCollection ancestor) { + super(key, delegate, ancestor); + } + + SortedSet getSortedSetDelegate() { + return (SortedSet)this.getDelegate(); + } + + @Override + public Comparator comparator() { + return this.getSortedSetDelegate().comparator(); + } + + @Override + public V first() { + this.refreshIfEmpty(); + return this.getSortedSetDelegate().first(); + } + + @Override + public V last() { + this.refreshIfEmpty(); + return this.getSortedSetDelegate().last(); + } + + @Override + public SortedSet headSet(V toElement) { + this.refreshIfEmpty(); + return new WrappedSortedSet(this.getKey(), this.getSortedSetDelegate().headSet(toElement), this.getAncestor() == null ? this : this.getAncestor()); + } + + @Override + public SortedSet subSet(V fromElement, V toElement) { + this.refreshIfEmpty(); + return new WrappedSortedSet(this.getKey(), this.getSortedSetDelegate().subSet(fromElement, toElement), this.getAncestor() == null ? this : this.getAncestor()); + } + + @Override + public SortedSet tailSet(V fromElement) { + this.refreshIfEmpty(); + return new WrappedSortedSet(this.getKey(), this.getSortedSetDelegate().tailSet(fromElement), this.getAncestor() == null ? this : this.getAncestor()); + } + } + + private class WrappedSet + extends WrappedCollection + implements Set { + WrappedSet(K key, Set delegate) { + super(key, delegate, null); + } + + @Override + public boolean removeAll(Collection c) { + if (c.isEmpty()) { + return false; + } + int oldSize = this.size(); + boolean changed = Sets.removeAllImpl((Set)this.delegate, c); + if (changed) { + int newSize = this.delegate.size(); + AbstractMapBasedMultimap.this.totalSize += newSize - oldSize; + this.removeIfEmpty(); + } + return changed; + } + } + + private class WrappedCollection + extends AbstractCollection { + final K key; + Collection delegate; + final WrappedCollection ancestor; + final Collection ancestorDelegate; + + WrappedCollection(K key, @Nullable Collection delegate, WrappedCollection ancestor) { + this.key = key; + this.delegate = delegate; + this.ancestor = ancestor; + this.ancestorDelegate = ancestor == null ? null : ancestor.getDelegate(); + } + + void refreshIfEmpty() { + Collection newDelegate; + if (this.ancestor != null) { + this.ancestor.refreshIfEmpty(); + if (this.ancestor.getDelegate() != this.ancestorDelegate) { + throw new ConcurrentModificationException(); + } + } else if (this.delegate.isEmpty() && (newDelegate = (Collection)AbstractMapBasedMultimap.this.map.get(this.key)) != null) { + this.delegate = newDelegate; + } + } + + void removeIfEmpty() { + if (this.ancestor != null) { + this.ancestor.removeIfEmpty(); + } else if (this.delegate.isEmpty()) { + AbstractMapBasedMultimap.this.map.remove(this.key); + } + } + + K getKey() { + return this.key; + } + + void addToMap() { + if (this.ancestor != null) { + this.ancestor.addToMap(); + } else { + AbstractMapBasedMultimap.this.map.put(this.key, this.delegate); + } + } + + @Override + public int size() { + this.refreshIfEmpty(); + return this.delegate.size(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + this.refreshIfEmpty(); + return this.delegate.equals(object); + } + + @Override + public int hashCode() { + this.refreshIfEmpty(); + return this.delegate.hashCode(); + } + + @Override + public String toString() { + this.refreshIfEmpty(); + return this.delegate.toString(); + } + + Collection getDelegate() { + return this.delegate; + } + + @Override + public Iterator iterator() { + this.refreshIfEmpty(); + return new WrappedIterator(); + } + + @Override + public boolean add(V value) { + this.refreshIfEmpty(); + boolean wasEmpty = this.delegate.isEmpty(); + boolean changed = this.delegate.add(value); + if (changed) { + AbstractMapBasedMultimap.this.totalSize++; + if (wasEmpty) { + this.addToMap(); + } + } + return changed; + } + + WrappedCollection getAncestor() { + return this.ancestor; + } + + @Override + public boolean addAll(Collection collection) { + if (collection.isEmpty()) { + return false; + } + int oldSize = this.size(); + boolean changed = this.delegate.addAll(collection); + if (changed) { + int newSize = this.delegate.size(); + AbstractMapBasedMultimap.this.totalSize += newSize - oldSize; + if (oldSize == 0) { + this.addToMap(); + } + } + return changed; + } + + @Override + public boolean contains(Object o) { + this.refreshIfEmpty(); + return this.delegate.contains(o); + } + + @Override + public boolean containsAll(Collection c) { + this.refreshIfEmpty(); + return this.delegate.containsAll(c); + } + + @Override + public void clear() { + int oldSize = this.size(); + if (oldSize == 0) { + return; + } + this.delegate.clear(); + AbstractMapBasedMultimap.this.totalSize -= oldSize; + this.removeIfEmpty(); + } + + @Override + public boolean remove(Object o) { + this.refreshIfEmpty(); + boolean changed = this.delegate.remove(o); + if (changed) { + AbstractMapBasedMultimap.this.totalSize--; + this.removeIfEmpty(); + } + return changed; + } + + @Override + public boolean removeAll(Collection c) { + if (c.isEmpty()) { + return false; + } + int oldSize = this.size(); + boolean changed = this.delegate.removeAll(c); + if (changed) { + int newSize = this.delegate.size(); + AbstractMapBasedMultimap.this.totalSize += newSize - oldSize; + this.removeIfEmpty(); + } + return changed; + } + + @Override + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + int oldSize = this.size(); + boolean changed = this.delegate.retainAll(c); + if (changed) { + int newSize = this.delegate.size(); + AbstractMapBasedMultimap.this.totalSize += newSize - oldSize; + this.removeIfEmpty(); + } + return changed; + } + + class WrappedIterator + implements Iterator { + final Iterator delegateIterator; + final Collection originalDelegate; + + WrappedIterator() { + this.originalDelegate = WrappedCollection.this.delegate; + this.delegateIterator = AbstractMapBasedMultimap.this.iteratorOrListIterator(WrappedCollection.this.delegate); + } + + WrappedIterator(Iterator delegateIterator) { + this.originalDelegate = WrappedCollection.this.delegate; + this.delegateIterator = delegateIterator; + } + + void validateIterator() { + WrappedCollection.this.refreshIfEmpty(); + if (WrappedCollection.this.delegate != this.originalDelegate) { + throw new ConcurrentModificationException(); + } + } + + @Override + public boolean hasNext() { + this.validateIterator(); + return this.delegateIterator.hasNext(); + } + + @Override + public V next() { + this.validateIterator(); + return this.delegateIterator.next(); + } + + @Override + public void remove() { + this.delegateIterator.remove(); + AbstractMapBasedMultimap.this.totalSize--; + WrappedCollection.this.removeIfEmpty(); + } + + Iterator getDelegateIterator() { + this.validateIterator(); + return this.delegateIterator; + } + } + } +} diff --git a/src/com/google/common/collect/AbstractMapBasedMultiset.java b/src/com/google/common/collect/AbstractMapBasedMultiset.java new file mode 100644 index 0000000..2efd32e --- /dev/null +++ b/src/com/google/common/collect/AbstractMapBasedMultiset.java @@ -0,0 +1,237 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMultiset; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Count; +import com.google.common.collect.Maps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.primitives.Ints; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +abstract class AbstractMapBasedMultiset +extends AbstractMultiset +implements Serializable { + private transient Map backingMap; + private transient long size; + @GwtIncompatible(value="not needed in emulated source.") + private static final long serialVersionUID = -2250766705698539974L; + + protected AbstractMapBasedMultiset(Map backingMap) { + this.backingMap = Preconditions.checkNotNull(backingMap); + this.size = super.size(); + } + + void setBackingMap(Map backingMap) { + this.backingMap = backingMap; + } + + @Override + public Set> entrySet() { + return super.entrySet(); + } + + @Override + Iterator> entryIterator() { + final Iterator> backingEntries = this.backingMap.entrySet().iterator(); + return new Iterator>(){ + Map.Entry toRemove; + + @Override + public boolean hasNext() { + return backingEntries.hasNext(); + } + + @Override + public Multiset.Entry next() { + Map.Entry mapEntry; + this.toRemove = mapEntry = (Map.Entry)backingEntries.next(); + return new Multisets.AbstractEntry(){ + + @Override + public E getElement() { + return mapEntry.getKey(); + } + + @Override + public int getCount() { + Count frequency; + Count count = (Count)mapEntry.getValue(); + if ((count == null || count.get() == 0) && (frequency = (Count)AbstractMapBasedMultiset.this.backingMap.get(this.getElement())) != null) { + return frequency.get(); + } + return count == null ? 0 : count.get(); + } + }; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.toRemove != null); + AbstractMapBasedMultiset.this.size -= this.toRemove.getValue().getAndSet(0); + backingEntries.remove(); + this.toRemove = null; + } + }; + } + + @Override + public void clear() { + for (Count frequency : this.backingMap.values()) { + frequency.set(0); + } + this.backingMap.clear(); + this.size = 0L; + } + + @Override + int distinctElements() { + return this.backingMap.size(); + } + + @Override + public int size() { + return Ints.saturatedCast(this.size); + } + + @Override + public Iterator iterator() { + return new MapBasedMultisetIterator(); + } + + @Override + public int count(@Nullable Object element) { + Count frequency = Maps.safeGet(this.backingMap, element); + return frequency == null ? 0 : frequency.get(); + } + + @Override + public int add(@Nullable E element, int occurrences) { + int oldCount; + if (occurrences == 0) { + return this.count(element); + } + Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences); + Count frequency = this.backingMap.get(element); + if (frequency == null) { + oldCount = 0; + this.backingMap.put(element, new Count(occurrences)); + } else { + oldCount = frequency.get(); + long newCount = (long)oldCount + (long)occurrences; + Preconditions.checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount); + frequency.getAndAdd(occurrences); + } + this.size += (long)occurrences; + return oldCount; + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + int numberRemoved; + if (occurrences == 0) { + return this.count(element); + } + Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences); + Count frequency = this.backingMap.get(element); + if (frequency == null) { + return 0; + } + int oldCount = frequency.get(); + if (oldCount > occurrences) { + numberRemoved = occurrences; + } else { + numberRemoved = oldCount; + this.backingMap.remove(element); + } + frequency.addAndGet(-numberRemoved); + this.size -= (long)numberRemoved; + return oldCount; + } + + @Override + public int setCount(@Nullable E element, int count) { + int oldCount; + CollectPreconditions.checkNonnegative(count, "count"); + if (count == 0) { + Count existingCounter = this.backingMap.remove(element); + oldCount = AbstractMapBasedMultiset.getAndSet(existingCounter, count); + } else { + Count existingCounter = this.backingMap.get(element); + oldCount = AbstractMapBasedMultiset.getAndSet(existingCounter, count); + if (existingCounter == null) { + this.backingMap.put(element, new Count(count)); + } + } + this.size += (long)(count - oldCount); + return oldCount; + } + + private static int getAndSet(Count i, int count) { + if (i == null) { + return 0; + } + return i.getAndSet(count); + } + + @GwtIncompatible(value="java.io.ObjectStreamException") + private void readObjectNoData() throws ObjectStreamException { + throw new InvalidObjectException("Stream data required"); + } + + private class MapBasedMultisetIterator + implements Iterator { + final Iterator> entryIterator; + Map.Entry currentEntry; + int occurrencesLeft; + boolean canRemove; + + MapBasedMultisetIterator() { + this.entryIterator = AbstractMapBasedMultiset.this.backingMap.entrySet().iterator(); + } + + @Override + public boolean hasNext() { + return this.occurrencesLeft > 0 || this.entryIterator.hasNext(); + } + + @Override + public E next() { + if (this.occurrencesLeft == 0) { + this.currentEntry = this.entryIterator.next(); + this.occurrencesLeft = this.currentEntry.getValue().get(); + } + --this.occurrencesLeft; + this.canRemove = true; + return this.currentEntry.getKey(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.canRemove); + int frequency = this.currentEntry.getValue().get(); + if (frequency <= 0) { + throw new ConcurrentModificationException(); + } + if (this.currentEntry.getValue().addAndGet(-1) == 0) { + this.entryIterator.remove(); + } + AbstractMapBasedMultiset.this.size--; + this.canRemove = false; + } + } +} diff --git a/src/com/google/common/collect/AbstractMapEntry.java b/src/com/google/common/collect/AbstractMapEntry.java new file mode 100644 index 0000000..2626d74 --- /dev/null +++ b/src/com/google/common/collect/AbstractMapEntry.java @@ -0,0 +1,49 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractMapEntry +implements Map.Entry { + AbstractMapEntry() { + } + + @Override + public abstract K getKey(); + + @Override + public abstract V getValue(); + + @Override + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry that = (Map.Entry)object; + return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue()); + } + return false; + } + + @Override + public int hashCode() { + K k = this.getKey(); + V v = this.getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.getKey())); + String string2 = String.valueOf(String.valueOf(this.getValue())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append("=").append(string2).toString(); + } +} diff --git a/src/com/google/common/collect/AbstractMultimap.java b/src/com/google/common/collect/AbstractMultimap.java new file mode 100644 index 0000000..8f8d0ac --- /dev/null +++ b/src/com/google/common/collect/AbstractMultimap.java @@ -0,0 +1,222 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Multiset; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractMultimap +implements Multimap { + private transient Collection> entries; + private transient Set keySet; + private transient Multiset keys; + private transient Collection values; + private transient Map> asMap; + + AbstractMultimap() { + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public boolean containsValue(@Nullable Object value) { + for (Collection collection : this.asMap().values()) { + if (!collection.contains(value)) continue; + return true; + } + return false; + } + + @Override + public boolean containsEntry(@Nullable Object key, @Nullable Object value) { + Collection collection = this.asMap().get(key); + return collection != null && collection.contains(value); + } + + @Override + public boolean remove(@Nullable Object key, @Nullable Object value) { + Collection collection = this.asMap().get(key); + return collection != null && collection.remove(value); + } + + @Override + public boolean put(@Nullable K key, @Nullable V value) { + return this.get(key).add(value); + } + + @Override + public boolean putAll(@Nullable K key, Iterable values) { + Preconditions.checkNotNull(values); + if (values instanceof Collection) { + Collection valueCollection = (Collection)values; + return !valueCollection.isEmpty() && this.get(key).addAll(valueCollection); + } + Iterator valueItr = values.iterator(); + return valueItr.hasNext() && Iterators.addAll(this.get(key), valueItr); + } + + @Override + public boolean putAll(Multimap multimap) { + boolean changed = false; + for (Map.Entry entry : multimap.entries()) { + changed |= this.put(entry.getKey(), entry.getValue()); + } + return changed; + } + + @Override + public Collection replaceValues(@Nullable K key, Iterable values) { + Preconditions.checkNotNull(values); + Collection result = this.removeAll(key); + this.putAll(key, values); + return result; + } + + @Override + public Collection> entries() { + Collection> result = this.entries; + return result == null ? (this.entries = this.createEntries()) : result; + } + + Collection> createEntries() { + if (this instanceof SetMultimap) { + return new EntrySet(); + } + return new Entries(); + } + + abstract Iterator> entryIterator(); + + @Override + public Set keySet() { + Set result = this.keySet; + return result == null ? (this.keySet = this.createKeySet()) : result; + } + + Set createKeySet() { + return new Maps.KeySet>(this.asMap()); + } + + @Override + public Multiset keys() { + Multiset result = this.keys; + return result == null ? (this.keys = this.createKeys()) : result; + } + + Multiset createKeys() { + return new Multimaps.Keys(this); + } + + @Override + public Collection values() { + Collection result = this.values; + return result == null ? (this.values = this.createValues()) : result; + } + + Collection createValues() { + return new Values(); + } + + Iterator valueIterator() { + return Maps.valueIterator(this.entries().iterator()); + } + + @Override + public Map> asMap() { + Map>> result = this.asMap; + return result == null ? (this.asMap = this.createAsMap()) : result; + } + + abstract Map> createAsMap(); + + @Override + public boolean equals(@Nullable Object object) { + return Multimaps.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return this.asMap().hashCode(); + } + + public String toString() { + return this.asMap().toString(); + } + + class Values + extends AbstractCollection { + Values() { + } + + @Override + public Iterator iterator() { + return AbstractMultimap.this.valueIterator(); + } + + @Override + public int size() { + return AbstractMultimap.this.size(); + } + + @Override + public boolean contains(@Nullable Object o) { + return AbstractMultimap.this.containsValue(o); + } + + @Override + public void clear() { + AbstractMultimap.this.clear(); + } + } + + private class EntrySet + extends Entries + implements Set> { + private EntrySet() { + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + @Override + public boolean equals(@Nullable Object obj) { + return Sets.equalsImpl(this, obj); + } + } + + private class Entries + extends Multimaps.Entries { + private Entries() { + } + + @Override + Multimap multimap() { + return AbstractMultimap.this; + } + + @Override + public Iterator> iterator() { + return AbstractMultimap.this.entryIterator(); + } + } +} diff --git a/src/com/google/common/collect/AbstractMultiset.java b/src/com/google/common/collect/AbstractMultiset.java new file mode 100644 index 0000000..7f51672 --- /dev/null +++ b/src/com/google/common/collect/AbstractMultiset.java @@ -0,0 +1,183 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractMultiset +extends AbstractCollection +implements Multiset { + private transient Set elementSet; + private transient Set> entrySet; + + AbstractMultiset() { + } + + @Override + public int size() { + return Multisets.sizeImpl(this); + } + + @Override + public boolean isEmpty() { + return this.entrySet().isEmpty(); + } + + @Override + public boolean contains(@Nullable Object element) { + return this.count(element) > 0; + } + + @Override + public Iterator iterator() { + return Multisets.iteratorImpl(this); + } + + @Override + public int count(@Nullable Object element) { + for (Multiset.Entry entry : this.entrySet()) { + if (!Objects.equal(entry.getElement(), element)) continue; + return entry.getCount(); + } + return 0; + } + + @Override + public boolean add(@Nullable E element) { + this.add(element, 1); + return true; + } + + @Override + public int add(@Nullable E element, int occurrences) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(@Nullable Object element) { + return this.remove(element, 1) > 0; + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + throw new UnsupportedOperationException(); + } + + @Override + public int setCount(@Nullable E element, int count) { + return Multisets.setCountImpl(this, element, count); + } + + @Override + public boolean setCount(@Nullable E element, int oldCount, int newCount) { + return Multisets.setCountImpl(this, element, oldCount, newCount); + } + + @Override + public boolean addAll(Collection elementsToAdd) { + return Multisets.addAllImpl(this, elementsToAdd); + } + + @Override + public boolean removeAll(Collection elementsToRemove) { + return Multisets.removeAllImpl(this, elementsToRemove); + } + + @Override + public boolean retainAll(Collection elementsToRetain) { + return Multisets.retainAllImpl(this, elementsToRetain); + } + + @Override + public void clear() { + Iterators.clear(this.entryIterator()); + } + + @Override + public Set elementSet() { + Set result = this.elementSet; + if (result == null) { + this.elementSet = result = this.createElementSet(); + } + return result; + } + + Set createElementSet() { + return new ElementSet(); + } + + abstract Iterator> entryIterator(); + + abstract int distinctElements(); + + @Override + public Set> entrySet() { + Set>> result = this.entrySet; + if (result == null) { + this.entrySet = result = this.createEntrySet(); + } + return result; + } + + Set> createEntrySet() { + return new EntrySet(); + } + + @Override + public boolean equals(@Nullable Object object) { + return Multisets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return this.entrySet().hashCode(); + } + + @Override + public String toString() { + return this.entrySet().toString(); + } + + class EntrySet + extends Multisets.EntrySet { + EntrySet() { + } + + @Override + Multiset multiset() { + return AbstractMultiset.this; + } + + @Override + public Iterator> iterator() { + return AbstractMultiset.this.entryIterator(); + } + + @Override + public int size() { + return AbstractMultiset.this.distinctElements(); + } + } + + class ElementSet + extends Multisets.ElementSet { + ElementSet() { + } + + @Override + Multiset multiset() { + return AbstractMultiset.this; + } + } +} diff --git a/src/com/google/common/collect/AbstractNavigableMap.java b/src/com/google/common/collect/AbstractNavigableMap.java new file mode 100644 index 0000000..b608561 --- /dev/null +++ b/src/com/google/common/collect/AbstractNavigableMap.java @@ -0,0 +1,187 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import java.util.AbstractMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import javax.annotation.Nullable; + +abstract class AbstractNavigableMap +extends AbstractMap +implements NavigableMap { + AbstractNavigableMap() { + } + + @Override + @Nullable + public abstract V get(@Nullable Object var1); + + @Override + @Nullable + public Map.Entry firstEntry() { + return Iterators.getNext(this.entryIterator(), null); + } + + @Override + @Nullable + public Map.Entry lastEntry() { + return Iterators.getNext(this.descendingEntryIterator(), null); + } + + @Override + @Nullable + public Map.Entry pollFirstEntry() { + return Iterators.pollNext(this.entryIterator()); + } + + @Override + @Nullable + public Map.Entry pollLastEntry() { + return Iterators.pollNext(this.descendingEntryIterator()); + } + + @Override + public K firstKey() { + Map.Entry entry = this.firstEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + @Override + public K lastKey() { + Map.Entry entry = this.lastEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + @Override + @Nullable + public Map.Entry lowerEntry(K key) { + return this.headMap(key, false).lastEntry(); + } + + @Override + @Nullable + public Map.Entry floorEntry(K key) { + return this.headMap(key, true).lastEntry(); + } + + @Override + @Nullable + public Map.Entry ceilingEntry(K key) { + return this.tailMap(key, true).firstEntry(); + } + + @Override + @Nullable + public Map.Entry higherEntry(K key) { + return this.tailMap(key, false).firstEntry(); + } + + @Override + public K lowerKey(K key) { + return Maps.keyOrNull(this.lowerEntry(key)); + } + + @Override + public K floorKey(K key) { + return Maps.keyOrNull(this.floorEntry(key)); + } + + @Override + public K ceilingKey(K key) { + return Maps.keyOrNull(this.ceilingEntry(key)); + } + + @Override + public K higherKey(K key) { + return Maps.keyOrNull(this.higherEntry(key)); + } + + abstract Iterator> entryIterator(); + + abstract Iterator> descendingEntryIterator(); + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public SortedMap headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public SortedMap tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Override + public NavigableSet navigableKeySet() { + return new Maps.NavigableKeySet(this); + } + + @Override + public Set keySet() { + return this.navigableKeySet(); + } + + @Override + public abstract int size(); + + @Override + public Set> entrySet() { + return new Maps.EntrySet(){ + + @Override + Map map() { + return AbstractNavigableMap.this; + } + + @Override + public Iterator> iterator() { + return AbstractNavigableMap.this.entryIterator(); + } + }; + } + + @Override + public NavigableSet descendingKeySet() { + return this.descendingMap().navigableKeySet(); + } + + @Override + public NavigableMap descendingMap() { + return new DescendingMap(); + } + + private final class DescendingMap + extends Maps.DescendingMap { + private DescendingMap() { + } + + @Override + NavigableMap forward() { + return AbstractNavigableMap.this; + } + + @Override + Iterator> entryIterator() { + return AbstractNavigableMap.this.descendingEntryIterator(); + } + } +} diff --git a/src/com/google/common/collect/AbstractRangeSet.java b/src/com/google/common/collect/AbstractRangeSet.java new file mode 100644 index 0000000..e574a9f --- /dev/null +++ b/src/com/google/common/collect/AbstractRangeSet.java @@ -0,0 +1,90 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import javax.annotation.Nullable; + +abstract class AbstractRangeSet +implements RangeSet { + AbstractRangeSet() { + } + + @Override + public boolean contains(C value) { + return this.rangeContaining(value) != null; + } + + @Override + public abstract Range rangeContaining(C var1); + + @Override + public boolean isEmpty() { + return this.asRanges().isEmpty(); + } + + @Override + public void add(Range range) { + throw new UnsupportedOperationException(); + } + + @Override + public void remove(Range range) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + this.remove(Range.all()); + } + + @Override + public boolean enclosesAll(RangeSet other) { + for (Range range : other.asRanges()) { + if (this.encloses(range)) continue; + return false; + } + return true; + } + + @Override + public void addAll(RangeSet other) { + for (Range range : other.asRanges()) { + this.add(range); + } + } + + @Override + public void removeAll(RangeSet other) { + for (Range range : other.asRanges()) { + this.remove(range); + } + } + + @Override + public abstract boolean encloses(Range var1); + + @Override + public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof RangeSet) { + RangeSet other = (RangeSet)obj; + return this.asRanges().equals(other.asRanges()); + } + return false; + } + + @Override + public final int hashCode() { + return this.asRanges().hashCode(); + } + + @Override + public final String toString() { + return this.asRanges().toString(); + } +} diff --git a/src/com/google/common/collect/AbstractSequentialIterator.java b/src/com/google/common/collect/AbstractSequentialIterator.java new file mode 100644 index 0000000..8d027fa --- /dev/null +++ b/src/com/google/common/collect/AbstractSequentialIterator.java @@ -0,0 +1,43 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.UnmodifiableIterator; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class AbstractSequentialIterator +extends UnmodifiableIterator { + private T nextOrNull; + + protected AbstractSequentialIterator(@Nullable T firstOrNull) { + this.nextOrNull = firstOrNull; + } + + protected abstract T computeNext(T var1); + + @Override + public final boolean hasNext() { + return this.nextOrNull != null; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + try { + T t = this.nextOrNull; + return t; + } + finally { + this.nextOrNull = this.computeNext(this.nextOrNull); + } + } +} diff --git a/src/com/google/common/collect/AbstractSetMultimap.java b/src/com/google/common/collect/AbstractSetMultimap.java new file mode 100644 index 0000000..aaa6d7b --- /dev/null +++ b/src/com/google/common/collect/AbstractSetMultimap.java @@ -0,0 +1,67 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.SetMultimap; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractSetMultimap +extends AbstractMapBasedMultimap +implements SetMultimap { + private static final long serialVersionUID = 7431625294878419160L; + + protected AbstractSetMultimap(Map> map) { + super(map); + } + + @Override + abstract Set createCollection(); + + @Override + Set createUnmodifiableEmptyCollection() { + return ImmutableSet.of(); + } + + @Override + public Set get(@Nullable K key) { + return (Set)super.get(key); + } + + @Override + public Set> entries() { + return (Set)super.entries(); + } + + @Override + public Set removeAll(@Nullable Object key) { + return (Set)super.removeAll(key); + } + + @Override + public Set replaceValues(@Nullable K key, Iterable values) { + return (Set)super.replaceValues(key, values); + } + + @Override + public Map> asMap() { + return super.asMap(); + } + + @Override + public boolean put(@Nullable K key, @Nullable V value) { + return super.put(key, value); + } + + @Override + public boolean equals(@Nullable Object object) { + return super.equals(object); + } +} diff --git a/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java b/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java new file mode 100644 index 0000000..f264eb4 --- /dev/null +++ b/src/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java @@ -0,0 +1,33 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractSortedSetMultimap; +import java.util.Collection; +import java.util.SortedMap; +import java.util.SortedSet; + +@GwtCompatible +abstract class AbstractSortedKeySortedSetMultimap +extends AbstractSortedSetMultimap { + AbstractSortedKeySortedSetMultimap(SortedMap> map) { + super(map); + } + + @Override + public SortedMap> asMap() { + return (SortedMap)super.asMap(); + } + + @Override + SortedMap> backingMap() { + return (SortedMap)super.backingMap(); + } + + @Override + public SortedSet keySet() { + return (SortedSet)super.keySet(); + } +} diff --git a/src/com/google/common/collect/AbstractSortedMultiset.java b/src/com/google/common/collect/AbstractSortedMultiset.java new file mode 100644 index 0000000..8ee29fb --- /dev/null +++ b/src/com/google/common/collect/AbstractSortedMultiset.java @@ -0,0 +1,127 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMultiset; +import com.google.common.collect.BoundType; +import com.google.common.collect.DescendingMultiset; +import com.google.common.collect.GwtTransient; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Ordering; +import com.google.common.collect.SortedMultiset; +import com.google.common.collect.SortedMultisets; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +abstract class AbstractSortedMultiset +extends AbstractMultiset +implements SortedMultiset { + @GwtTransient + final Comparator comparator; + private transient SortedMultiset descendingMultiset; + + AbstractSortedMultiset() { + this(Ordering.natural()); + } + + AbstractSortedMultiset(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + @Override + public NavigableSet elementSet() { + return (NavigableSet)super.elementSet(); + } + + @Override + NavigableSet createElementSet() { + return new SortedMultisets.NavigableElementSet(this); + } + + @Override + public Comparator comparator() { + return this.comparator; + } + + @Override + public Multiset.Entry firstEntry() { + Iterator entryIterator = this.entryIterator(); + return entryIterator.hasNext() ? entryIterator.next() : null; + } + + @Override + public Multiset.Entry lastEntry() { + Iterator> entryIterator = this.descendingEntryIterator(); + return entryIterator.hasNext() ? entryIterator.next() : null; + } + + @Override + public Multiset.Entry pollFirstEntry() { + Iterator entryIterator = this.entryIterator(); + if (entryIterator.hasNext()) { + Multiset.Entry result = entryIterator.next(); + result = Multisets.immutableEntry(result.getElement(), result.getCount()); + entryIterator.remove(); + return result; + } + return null; + } + + @Override + public Multiset.Entry pollLastEntry() { + Iterator> entryIterator = this.descendingEntryIterator(); + if (entryIterator.hasNext()) { + Multiset.Entry result = entryIterator.next(); + result = Multisets.immutableEntry(result.getElement(), result.getCount()); + entryIterator.remove(); + return result; + } + return null; + } + + @Override + public SortedMultiset subMultiset(@Nullable E fromElement, BoundType fromBoundType, @Nullable E toElement, BoundType toBoundType) { + Preconditions.checkNotNull(fromBoundType); + Preconditions.checkNotNull(toBoundType); + return this.tailMultiset(fromElement, fromBoundType).headMultiset(toElement, toBoundType); + } + + abstract Iterator> descendingEntryIterator(); + + Iterator descendingIterator() { + return Multisets.iteratorImpl(this.descendingMultiset()); + } + + @Override + public SortedMultiset descendingMultiset() { + SortedMultiset result = this.descendingMultiset; + return result == null ? (this.descendingMultiset = this.createDescendingMultiset()) : result; + } + + SortedMultiset createDescendingMultiset() { + return new DescendingMultiset(){ + + @Override + SortedMultiset forwardMultiset() { + return AbstractSortedMultiset.this; + } + + @Override + Iterator> entryIterator() { + return AbstractSortedMultiset.this.descendingEntryIterator(); + } + + @Override + public Iterator iterator() { + return AbstractSortedMultiset.this.descendingIterator(); + } + }; + } +} diff --git a/src/com/google/common/collect/AbstractSortedSetMultimap.java b/src/com/google/common/collect/AbstractSortedSetMultimap.java new file mode 100644 index 0000000..b6ff1d7 --- /dev/null +++ b/src/com/google/common/collect/AbstractSortedSetMultimap.java @@ -0,0 +1,63 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractSetMultimap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.SortedSetMultimap; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractSortedSetMultimap +extends AbstractSetMultimap +implements SortedSetMultimap { + private static final long serialVersionUID = 430848587173315748L; + + protected AbstractSortedSetMultimap(Map> map) { + super(map); + } + + @Override + abstract SortedSet createCollection(); + + @Override + SortedSet createUnmodifiableEmptyCollection() { + Comparator comparator = this.valueComparator(); + if (comparator == null) { + return Collections.unmodifiableSortedSet(this.createCollection()); + } + return ImmutableSortedSet.emptySet(this.valueComparator()); + } + + @Override + public SortedSet get(@Nullable K key) { + return (SortedSet)super.get((Object)key); + } + + @Override + public SortedSet removeAll(@Nullable Object key) { + return (SortedSet)super.removeAll(key); + } + + @Override + public SortedSet replaceValues(@Nullable K key, Iterable values) { + return (SortedSet)super.replaceValues((Object)key, (Iterable)values); + } + + @Override + public Map> asMap() { + return super.asMap(); + } + + @Override + public Collection values() { + return super.values(); + } +} diff --git a/src/com/google/common/collect/AbstractTable.java b/src/com/google/common/collect/AbstractTable.java new file mode 100644 index 0000000..f5c8da1 --- /dev/null +++ b/src/com/google/common/collect/AbstractTable.java @@ -0,0 +1,211 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Collections2; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Table; +import com.google.common.collect.Tables; +import com.google.common.collect.TransformedIterator; +import java.util.AbstractCollection; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class AbstractTable +implements Table { + private transient Set> cellSet; + private transient Collection values; + + AbstractTable() { + } + + @Override + public boolean containsRow(@Nullable Object rowKey) { + return Maps.safeContainsKey(this.rowMap(), rowKey); + } + + @Override + public boolean containsColumn(@Nullable Object columnKey) { + return Maps.safeContainsKey(this.columnMap(), columnKey); + } + + @Override + public Set rowKeySet() { + return this.rowMap().keySet(); + } + + @Override + public Set columnKeySet() { + return this.columnMap().keySet(); + } + + @Override + public boolean containsValue(@Nullable Object value) { + for (Map row : this.rowMap().values()) { + if (!row.containsValue(value)) continue; + return true; + } + return false; + } + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + Map row = Maps.safeGet(this.rowMap(), rowKey); + return row != null && Maps.safeContainsKey(row, columnKey); + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + Map row = Maps.safeGet(this.rowMap(), rowKey); + return row == null ? null : (V)Maps.safeGet(row, columnKey); + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public void clear() { + Iterators.clear(this.cellSet().iterator()); + } + + @Override + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) { + Map row = Maps.safeGet(this.rowMap(), rowKey); + return row == null ? null : (V)Maps.safeRemove(row, columnKey); + } + + @Override + public V put(R rowKey, C columnKey, V value) { + return this.row(rowKey).put(columnKey, value); + } + + @Override + public void putAll(Table table) { + for (Table.Cell cell : table.cellSet()) { + this.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + } + + @Override + public Set> cellSet() { + Set> result = this.cellSet; + return result == null ? (this.cellSet = this.createCellSet()) : result; + } + + Set> createCellSet() { + return new CellSet(); + } + + abstract Iterator> cellIterator(); + + @Override + public Collection values() { + Collection result = this.values; + return result == null ? (this.values = this.createValues()) : result; + } + + Collection createValues() { + return new Values(); + } + + Iterator valuesIterator() { + return new TransformedIterator, V>(this.cellSet().iterator()){ + + @Override + V transform(Table.Cell cell) { + return cell.getValue(); + } + }; + } + + @Override + public boolean equals(@Nullable Object obj) { + return Tables.equalsImpl(this, obj); + } + + @Override + public int hashCode() { + return this.cellSet().hashCode(); + } + + public String toString() { + return this.rowMap().toString(); + } + + class Values + extends AbstractCollection { + Values() { + } + + @Override + public Iterator iterator() { + return AbstractTable.this.valuesIterator(); + } + + @Override + public boolean contains(Object o) { + return AbstractTable.this.containsValue(o); + } + + @Override + public void clear() { + AbstractTable.this.clear(); + } + + @Override + public int size() { + return AbstractTable.this.size(); + } + } + + class CellSet + extends AbstractSet> { + CellSet() { + } + + @Override + public boolean contains(Object o) { + if (o instanceof Table.Cell) { + Table.Cell cell = (Table.Cell)o; + Map row = Maps.safeGet(AbstractTable.this.rowMap(), cell.getRowKey()); + return row != null && Collections2.safeContains(row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue())); + } + return false; + } + + @Override + public boolean remove(@Nullable Object o) { + if (o instanceof Table.Cell) { + Table.Cell cell = (Table.Cell)o; + Map row = Maps.safeGet(AbstractTable.this.rowMap(), cell.getRowKey()); + return row != null && Collections2.safeRemove(row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue())); + } + return false; + } + + @Override + public void clear() { + AbstractTable.this.clear(); + } + + @Override + public Iterator> iterator() { + return AbstractTable.this.cellIterator(); + } + + @Override + public int size() { + return AbstractTable.this.size(); + } + } +} diff --git a/src/com/google/common/collect/AllEqualOrdering.java b/src/com/google/common/collect/AllEqualOrdering.java new file mode 100644 index 0000000..cf2db97 --- /dev/null +++ b/src/com/google/common/collect/AllEqualOrdering.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class AllEqualOrdering +extends Ordering +implements Serializable { + static final AllEqualOrdering INSTANCE = new AllEqualOrdering(); + private static final long serialVersionUID = 0L; + + AllEqualOrdering() { + } + + @Override + public int compare(@Nullable Object left, @Nullable Object right) { + return 0; + } + + @Override + public List sortedCopy(Iterable iterable) { + return Lists.newArrayList(iterable); + } + + @Override + public ImmutableList immutableSortedCopy(Iterable iterable) { + return ImmutableList.copyOf(iterable); + } + + @Override + public Ordering reverse() { + return this; + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "Ordering.allEqual()"; + } +} diff --git a/src/com/google/common/collect/ArrayListMultimap.java b/src/com/google/common/collect/ArrayListMultimap.java new file mode 100644 index 0000000..c3960b2 --- /dev/null +++ b/src/com/google/common/collect/ArrayListMultimap.java @@ -0,0 +1,87 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.AbstractListMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Serialization; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +@GwtCompatible(serializable=true, emulated=true) +public final class ArrayListMultimap +extends AbstractListMultimap { + private static final int DEFAULT_VALUES_PER_KEY = 3; + @VisibleForTesting + transient int expectedValuesPerKey; + @GwtIncompatible(value="Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static ArrayListMultimap create() { + return new ArrayListMultimap(); + } + + public static ArrayListMultimap create(int expectedKeys, int expectedValuesPerKey) { + return new ArrayListMultimap(expectedKeys, expectedValuesPerKey); + } + + public static ArrayListMultimap create(Multimap multimap) { + return new ArrayListMultimap(multimap); + } + + private ArrayListMultimap() { + super(new HashMap()); + this.expectedValuesPerKey = 3; + } + + private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) { + super(Maps.newHashMapWithExpectedSize(expectedKeys)); + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + this.expectedValuesPerKey = expectedValuesPerKey; + } + + private ArrayListMultimap(Multimap multimap) { + this(multimap.keySet().size(), multimap instanceof ArrayListMultimap ? ((ArrayListMultimap)multimap).expectedValuesPerKey : 3); + this.putAll((Multimap)multimap); + } + + @Override + List createCollection() { + return new ArrayList(this.expectedValuesPerKey); + } + + public void trimToSize() { + for (Collection collection : this.backingMap().values()) { + ArrayList arrayList = (ArrayList)collection; + arrayList.trimToSize(); + } + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeInt(this.expectedValuesPerKey); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.expectedValuesPerKey = stream.readInt(); + int distinctKeys = Serialization.readCount(stream); + HashMap map = Maps.newHashMapWithExpectedSize(distinctKeys); + this.setMap(map); + Serialization.populateMultimap(this, stream, distinctKeys); + } +} diff --git a/src/com/google/common/collect/ArrayTable.java b/src/com/google/common/collect/ArrayTable.java new file mode 100644 index 0000000..d302eff --- /dev/null +++ b/src/com/google/common/collect/ArrayTable.java @@ -0,0 +1,503 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIndexedListIterator; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.AbstractTable; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Table; +import com.google.common.collect.Tables; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible(emulated=true) +public final class ArrayTable +extends AbstractTable +implements Serializable { + private final ImmutableList rowList; + private final ImmutableList columnList; + private final ImmutableMap rowKeyToIndex; + private final ImmutableMap columnKeyToIndex; + private final V[][] array; + private transient ColumnMap columnMap; + private transient RowMap rowMap; + private static final long serialVersionUID = 0L; + + public static ArrayTable create(Iterable rowKeys, Iterable columnKeys) { + return new ArrayTable(rowKeys, columnKeys); + } + + public static ArrayTable create(Table table) { + return table instanceof ArrayTable ? new ArrayTable((ArrayTable)table) : new ArrayTable(table); + } + + private ArrayTable(Iterable rowKeys, Iterable columnKeys) { + this.rowList = ImmutableList.copyOf(rowKeys); + this.columnList = ImmutableList.copyOf(columnKeys); + Preconditions.checkArgument(!this.rowList.isEmpty()); + Preconditions.checkArgument(!this.columnList.isEmpty()); + this.rowKeyToIndex = ArrayTable.index(this.rowList); + this.columnKeyToIndex = ArrayTable.index(this.columnList); + Object[][] tmpArray = new Object[this.rowList.size()][this.columnList.size()]; + this.array = tmpArray; + this.eraseAll(); + } + + private static ImmutableMap index(List list) { + ImmutableMap.Builder columnBuilder = ImmutableMap.builder(); + for (int i = 0; i < list.size(); ++i) { + columnBuilder.put(list.get(i), i); + } + return columnBuilder.build(); + } + + private ArrayTable(Table table) { + this(table.rowKeySet(), table.columnKeySet()); + this.putAll(table); + } + + private ArrayTable(ArrayTable table) { + this.rowList = table.rowList; + this.columnList = table.columnList; + this.rowKeyToIndex = table.rowKeyToIndex; + this.columnKeyToIndex = table.columnKeyToIndex; + Object[][] copy = new Object[this.rowList.size()][this.columnList.size()]; + this.array = copy; + this.eraseAll(); + for (int i = 0; i < this.rowList.size(); ++i) { + System.arraycopy(table.array[i], 0, copy[i], 0, table.array[i].length); + } + } + + public ImmutableList rowKeyList() { + return this.rowList; + } + + public ImmutableList columnKeyList() { + return this.columnList; + } + + public V at(int rowIndex, int columnIndex) { + Preconditions.checkElementIndex(rowIndex, this.rowList.size()); + Preconditions.checkElementIndex(columnIndex, this.columnList.size()); + return this.array[rowIndex][columnIndex]; + } + + public V set(int rowIndex, int columnIndex, @Nullable V value) { + Preconditions.checkElementIndex(rowIndex, this.rowList.size()); + Preconditions.checkElementIndex(columnIndex, this.columnList.size()); + V oldValue = this.array[rowIndex][columnIndex]; + this.array[rowIndex][columnIndex] = value; + return oldValue; + } + + @GwtIncompatible(value="reflection") + public V[][] toArray(Class valueClass) { + Object[][] copy = (Object[][])Array.newInstance(valueClass, this.rowList.size(), this.columnList.size()); + for (int i = 0; i < this.rowList.size(); ++i) { + System.arraycopy(this.array[i], 0, copy[i], 0, this.array[i].length); + } + return copy; + } + + @Override + @Deprecated + public void clear() { + throw new UnsupportedOperationException(); + } + + public void eraseAll() { + for (Object[] objectArray : this.array) { + Arrays.fill(objectArray, null); + } + } + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + return this.containsRow(rowKey) && this.containsColumn(columnKey); + } + + @Override + public boolean containsColumn(@Nullable Object columnKey) { + return this.columnKeyToIndex.containsKey(columnKey); + } + + @Override + public boolean containsRow(@Nullable Object rowKey) { + return this.rowKeyToIndex.containsKey(rowKey); + } + + @Override + public boolean containsValue(@Nullable Object value) { + V[][] arr$ = this.array; + int len$ = arr$.length; + for (int i$ = 0; i$ < len$; ++i$) { + V[] row; + for (V element : row = arr$[i$]) { + if (!Objects.equal(value, element)) continue; + return true; + } + } + return false; + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + Integer rowIndex = this.rowKeyToIndex.get(rowKey); + Integer columnIndex = this.columnKeyToIndex.get(columnKey); + return rowIndex == null || columnIndex == null ? null : (V)this.at(rowIndex, columnIndex); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public V put(R rowKey, C columnKey, @Nullable V value) { + Preconditions.checkNotNull(rowKey); + Preconditions.checkNotNull(columnKey); + Integer rowIndex = this.rowKeyToIndex.get(rowKey); + Preconditions.checkArgument(rowIndex != null, "Row %s not in %s", rowKey, this.rowList); + Integer columnIndex = this.columnKeyToIndex.get(columnKey); + Preconditions.checkArgument(columnIndex != null, "Column %s not in %s", columnKey, this.columnList); + return this.set(rowIndex, columnIndex, value); + } + + @Override + public void putAll(Table table) { + super.putAll(table); + } + + @Override + @Deprecated + public V remove(Object rowKey, Object columnKey) { + throw new UnsupportedOperationException(); + } + + public V erase(@Nullable Object rowKey, @Nullable Object columnKey) { + Integer rowIndex = this.rowKeyToIndex.get(rowKey); + Integer columnIndex = this.columnKeyToIndex.get(columnKey); + if (rowIndex == null || columnIndex == null) { + return null; + } + return this.set(rowIndex, columnIndex, null); + } + + @Override + public int size() { + return this.rowList.size() * this.columnList.size(); + } + + @Override + public Set> cellSet() { + return super.cellSet(); + } + + @Override + Iterator> cellIterator() { + return new AbstractIndexedListIterator>(this.size()){ + + @Override + protected Table.Cell get(final int index) { + return new Tables.AbstractCell(){ + final int rowIndex; + final int columnIndex; + { + this.rowIndex = index / ArrayTable.this.columnList.size(); + this.columnIndex = index % ArrayTable.this.columnList.size(); + } + + @Override + public R getRowKey() { + return ArrayTable.this.rowList.get(this.rowIndex); + } + + @Override + public C getColumnKey() { + return ArrayTable.this.columnList.get(this.columnIndex); + } + + @Override + public V getValue() { + return ArrayTable.this.at(this.rowIndex, this.columnIndex); + } + }; + } + }; + } + + @Override + public Map column(C columnKey) { + Preconditions.checkNotNull(columnKey); + Integer columnIndex = this.columnKeyToIndex.get(columnKey); + return columnIndex == null ? ImmutableMap.of() : new Column(columnIndex); + } + + @Override + public ImmutableSet columnKeySet() { + return this.columnKeyToIndex.keySet(); + } + + @Override + public Map> columnMap() { + ColumnMap map = this.columnMap; + return map == null ? (this.columnMap = new ColumnMap()) : map; + } + + @Override + public Map row(R rowKey) { + Preconditions.checkNotNull(rowKey); + Integer rowIndex = this.rowKeyToIndex.get(rowKey); + return rowIndex == null ? ImmutableMap.of() : new Row(rowIndex); + } + + @Override + public ImmutableSet rowKeySet() { + return this.rowKeyToIndex.keySet(); + } + + @Override + public Map> rowMap() { + RowMap map = this.rowMap; + return map == null ? (this.rowMap = new RowMap()) : map; + } + + @Override + public Collection values() { + return super.values(); + } + + private class RowMap + extends ArrayMap> { + private RowMap() { + super(ArrayTable.this.rowKeyToIndex); + } + + @Override + String getKeyRole() { + return "Row"; + } + + @Override + Map getValue(int index) { + return new Row(index); + } + + @Override + Map setValue(int index, Map newValue) { + throw new UnsupportedOperationException(); + } + + @Override + public Map put(R key, Map value) { + throw new UnsupportedOperationException(); + } + } + + private class Row + extends ArrayMap { + final int rowIndex; + + Row(int rowIndex) { + super(ArrayTable.this.columnKeyToIndex); + this.rowIndex = rowIndex; + } + + @Override + String getKeyRole() { + return "Column"; + } + + @Override + V getValue(int index) { + return ArrayTable.this.at(this.rowIndex, index); + } + + @Override + V setValue(int index, V newValue) { + return ArrayTable.this.set(this.rowIndex, index, newValue); + } + } + + private class ColumnMap + extends ArrayMap> { + private ColumnMap() { + super(ArrayTable.this.columnKeyToIndex); + } + + @Override + String getKeyRole() { + return "Column"; + } + + @Override + Map getValue(int index) { + return new Column(index); + } + + @Override + Map setValue(int index, Map newValue) { + throw new UnsupportedOperationException(); + } + + @Override + public Map put(C key, Map value) { + throw new UnsupportedOperationException(); + } + } + + private class Column + extends ArrayMap { + final int columnIndex; + + Column(int columnIndex) { + super(ArrayTable.this.rowKeyToIndex); + this.columnIndex = columnIndex; + } + + @Override + String getKeyRole() { + return "Row"; + } + + @Override + V getValue(int index) { + return ArrayTable.this.at(index, this.columnIndex); + } + + @Override + V setValue(int index, V newValue) { + return ArrayTable.this.set(index, this.columnIndex, newValue); + } + } + + private static abstract class ArrayMap + extends Maps.ImprovedAbstractMap { + private final ImmutableMap keyIndex; + + private ArrayMap(ImmutableMap keyIndex) { + this.keyIndex = keyIndex; + } + + @Override + public Set keySet() { + return this.keyIndex.keySet(); + } + + K getKey(int index) { + return (K)((ImmutableCollection)((Object)this.keyIndex.keySet())).asList().get(index); + } + + abstract String getKeyRole(); + + @Nullable + abstract V getValue(int var1); + + @Nullable + abstract V setValue(int var1, V var2); + + @Override + public int size() { + return this.keyIndex.size(); + } + + @Override + public boolean isEmpty() { + return this.keyIndex.isEmpty(); + } + + @Override + protected Set> createEntrySet() { + return new Maps.EntrySet(){ + + @Override + Map map() { + return ArrayMap.this; + } + + @Override + public Iterator> iterator() { + return new AbstractIndexedListIterator>(this.size()){ + + @Override + protected Map.Entry get(final int index) { + return new AbstractMapEntry(){ + + @Override + public K getKey() { + return ArrayMap.this.getKey(index); + } + + @Override + public V getValue() { + return ArrayMap.this.getValue(index); + } + + @Override + public V setValue(V value) { + return ArrayMap.this.setValue(index, value); + } + }; + } + }; + } + }; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.keyIndex.containsKey(key); + } + + @Override + public V get(@Nullable Object key) { + Integer index = this.keyIndex.get(key); + if (index == null) { + return null; + } + return this.getValue(index); + } + + @Override + public V put(K key, V value) { + Integer index = this.keyIndex.get(key); + if (index == null) { + String string = String.valueOf(String.valueOf(this.getKeyRole())); + String string2 = String.valueOf(String.valueOf(key)); + String string3 = String.valueOf(String.valueOf(this.keyIndex.keySet())); + throw new IllegalArgumentException(new StringBuilder(9 + string.length() + string2.length() + string3.length()).append(string).append(" ").append(string2).append(" not in ").append(string3).toString()); + } + return this.setValue(index, value); + } + + @Override + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/com/google/common/collect/BiMap.java b/src/com/google/common/collect/BiMap.java new file mode 100644 index 0000000..748e1d5 --- /dev/null +++ b/src/com/google/common/collect/BiMap.java @@ -0,0 +1,26 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public interface BiMap +extends Map { + @Override + public V put(@Nullable K var1, @Nullable V var2); + + public V forcePut(@Nullable K var1, @Nullable V var2); + + @Override + public void putAll(Map var1); + + @Override + public Set values(); + + public BiMap inverse(); +} diff --git a/src/com/google/common/collect/BinaryTreeTraverser.java b/src/com/google/common/collect/BinaryTreeTraverser.java new file mode 100644 index 0000000..adfc17c --- /dev/null +++ b/src/com/google/common/collect/BinaryTreeTraverser.java @@ -0,0 +1,174 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.TreeTraverser; +import com.google.common.collect.UnmodifiableIterator; +import java.util.ArrayDeque; +import java.util.BitSet; +import java.util.Deque; +import java.util.Iterator; + +@Beta +@GwtCompatible(emulated=true) +public abstract class BinaryTreeTraverser +extends TreeTraverser { + public abstract Optional leftChild(T var1); + + public abstract Optional rightChild(T var1); + + @Override + public final Iterable children(final T root) { + Preconditions.checkNotNull(root); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return new AbstractIterator(){ + boolean doneLeft; + boolean doneRight; + + @Override + protected T computeNext() { + if (!this.doneLeft) { + this.doneLeft = true; + Optional left = BinaryTreeTraverser.this.leftChild(root); + if (left.isPresent()) { + return left.get(); + } + } + if (!this.doneRight) { + this.doneRight = true; + Optional right = BinaryTreeTraverser.this.rightChild(root); + if (right.isPresent()) { + return right.get(); + } + } + return this.endOfData(); + } + }; + } + }; + } + + @Override + UnmodifiableIterator preOrderIterator(T root) { + return new PreOrderIterator(root); + } + + @Override + UnmodifiableIterator postOrderIterator(T root) { + return new PostOrderIterator(root); + } + + public final FluentIterable inOrderTraversal(final T root) { + Preconditions.checkNotNull(root); + return new FluentIterable(){ + + @Override + public UnmodifiableIterator iterator() { + return new InOrderIterator(root); + } + }; + } + + private static void pushIfPresent(Deque stack, Optional node) { + if (node.isPresent()) { + stack.addLast(node.get()); + } + } + + private final class InOrderIterator + extends AbstractIterator { + private final Deque stack = new ArrayDeque(); + private final BitSet hasExpandedLeft = new BitSet(); + + InOrderIterator(T root) { + this.stack.addLast(root); + } + + @Override + protected T computeNext() { + while (!this.stack.isEmpty()) { + Object node = this.stack.getLast(); + if (this.hasExpandedLeft.get(this.stack.size() - 1)) { + this.stack.removeLast(); + this.hasExpandedLeft.clear(this.stack.size()); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.rightChild(node)); + return node; + } + this.hasExpandedLeft.set(this.stack.size() - 1); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.leftChild(node)); + } + return this.endOfData(); + } + } + + private final class PostOrderIterator + extends UnmodifiableIterator { + private final Deque stack = new ArrayDeque(); + private final BitSet hasExpanded; + + PostOrderIterator(T root) { + this.stack.addLast(root); + this.hasExpanded = new BitSet(); + } + + @Override + public boolean hasNext() { + return !this.stack.isEmpty(); + } + + @Override + public T next() { + while (true) { + Object node = this.stack.getLast(); + boolean expandedNode = this.hasExpanded.get(this.stack.size() - 1); + if (expandedNode) { + this.stack.removeLast(); + this.hasExpanded.clear(this.stack.size()); + return node; + } + this.hasExpanded.set(this.stack.size() - 1); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.rightChild(node)); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.leftChild(node)); + } + } + } + + private final class PreOrderIterator + extends UnmodifiableIterator + implements PeekingIterator { + private final Deque stack = new ArrayDeque(); + + PreOrderIterator(T root) { + this.stack.addLast(root); + } + + @Override + public boolean hasNext() { + return !this.stack.isEmpty(); + } + + @Override + public T next() { + Object result = this.stack.removeLast(); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.rightChild(result)); + BinaryTreeTraverser.pushIfPresent(this.stack, BinaryTreeTraverser.this.leftChild(result)); + return result; + } + + @Override + public T peek() { + return this.stack.getLast(); + } + } +} diff --git a/src/com/google/common/collect/BoundType.java b/src/com/google/common/collect/BoundType.java new file mode 100644 index 0000000..e28fc0c --- /dev/null +++ b/src/com/google/common/collect/BoundType.java @@ -0,0 +1,32 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public enum BoundType { + OPEN{ + + @Override + BoundType flip() { + return CLOSED; + } + } + , + CLOSED{ + + @Override + BoundType flip() { + return OPEN; + } + }; + + + static BoundType forBoolean(boolean inclusive) { + return inclusive ? CLOSED : OPEN; + } + + abstract BoundType flip(); +} diff --git a/src/com/google/common/collect/ByFunctionOrdering.java b/src/com/google/common/collect/ByFunctionOrdering.java new file mode 100644 index 0000000..135880e --- /dev/null +++ b/src/com/google/common/collect/ByFunctionOrdering.java @@ -0,0 +1,53 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class ByFunctionOrdering +extends Ordering +implements Serializable { + final Function function; + final Ordering ordering; + private static final long serialVersionUID = 0L; + + ByFunctionOrdering(Function function, Ordering ordering) { + this.function = Preconditions.checkNotNull(function); + this.ordering = Preconditions.checkNotNull(ordering); + } + + @Override + public int compare(F left, F right) { + return this.ordering.compare(this.function.apply(left), this.function.apply(right)); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof ByFunctionOrdering) { + ByFunctionOrdering that = (ByFunctionOrdering)object; + return this.function.equals(that.function) && this.ordering.equals(that.ordering); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.function, this.ordering); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.ordering)); + String string2 = String.valueOf(String.valueOf(this.function)); + return new StringBuilder(13 + string.length() + string2.length()).append(string).append(".onResultOf(").append(string2).append(")").toString(); + } +} diff --git a/src/com/google/common/collect/CartesianList.java b/src/com/google/common/collect/CartesianList.java new file mode 100644 index 0000000..8d7be2e --- /dev/null +++ b/src/com/google/common/collect/CartesianList.java @@ -0,0 +1,100 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.math.IntMath; +import java.util.AbstractList; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; +import javax.annotation.Nullable; + +@GwtCompatible +final class CartesianList +extends AbstractList> +implements RandomAccess { + private final transient ImmutableList> axes; + private final transient int[] axesSizeProduct; + + static List> create(List> lists) { + ImmutableList.Builder axesBuilder = new ImmutableList.Builder(lists.size()); + for (List list : lists) { + ImmutableList copy = ImmutableList.copyOf(list); + if (copy.isEmpty()) { + return ImmutableList.of(); + } + axesBuilder.add(copy); + } + return new CartesianList(axesBuilder.build()); + } + + CartesianList(ImmutableList> axes) { + this.axes = axes; + int[] axesSizeProduct = new int[axes.size() + 1]; + axesSizeProduct[axes.size()] = 1; + try { + for (int i = axes.size() - 1; i >= 0; --i) { + axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[i + 1], ((List)axes.get(i)).size()); + } + } + catch (ArithmeticException e) { + throw new IllegalArgumentException("Cartesian product too large; must have size at most Integer.MAX_VALUE"); + } + this.axesSizeProduct = axesSizeProduct; + } + + private int getAxisIndexForProductIndex(int index, int axis) { + return index / this.axesSizeProduct[axis + 1] % ((List)this.axes.get(axis)).size(); + } + + @Override + public ImmutableList get(final int index) { + Preconditions.checkElementIndex(index, this.size()); + return new ImmutableList(){ + + @Override + public int size() { + return CartesianList.this.axes.size(); + } + + @Override + public E get(int axis) { + Preconditions.checkElementIndex(axis, this.size()); + int axisIndex = CartesianList.this.getAxisIndexForProductIndex(index, axis); + return ((List)CartesianList.this.axes.get(axis)).get(axisIndex); + } + + @Override + boolean isPartialView() { + return true; + } + }; + } + + @Override + public int size() { + return this.axesSizeProduct[0]; + } + + @Override + public boolean contains(@Nullable Object o) { + if (!(o instanceof List)) { + return false; + } + List list = (List)o; + if (list.size() != this.axes.size()) { + return false; + } + ListIterator itr = list.listIterator(); + while (itr.hasNext()) { + int index = itr.nextIndex(); + if (((List)this.axes.get(index)).contains(itr.next())) continue; + return false; + } + return true; + } +} diff --git a/src/com/google/common/collect/ClassToInstanceMap.java b/src/com/google/common/collect/ClassToInstanceMap.java new file mode 100644 index 0000000..5810c00 --- /dev/null +++ b/src/com/google/common/collect/ClassToInstanceMap.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public interface ClassToInstanceMap +extends Map, B> { + public T getInstance(Class var1); + + public T putInstance(Class var1, @Nullable T var2); +} diff --git a/src/com/google/common/collect/CollectPreconditions.java b/src/com/google/common/collect/CollectPreconditions.java new file mode 100644 index 0000000..d524b3c --- /dev/null +++ b/src/com/google/common/collect/CollectPreconditions.java @@ -0,0 +1,37 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; + +@GwtCompatible +final class CollectPreconditions { + CollectPreconditions() { + } + + static void checkEntryNotNull(Object key, Object value) { + if (key == null) { + String string = String.valueOf(String.valueOf(value)); + throw new NullPointerException(new StringBuilder(24 + string.length()).append("null key in entry: null=").append(string).toString()); + } + if (value == null) { + String string = String.valueOf(String.valueOf(key)); + throw new NullPointerException(new StringBuilder(26 + string.length()).append("null value in entry: ").append(string).append("=null").toString()); + } + } + + static int checkNonnegative(int value, String name) { + if (value < 0) { + String string = String.valueOf(String.valueOf(name)); + int n = value; + throw new IllegalArgumentException(new StringBuilder(40 + string.length()).append(string).append(" cannot be negative but was: ").append(n).toString()); + } + return value; + } + + static void checkRemove(boolean canRemove) { + Preconditions.checkState(canRemove, "no calls to next() since the last call to remove()"); + } +} diff --git a/src/com/google/common/collect/Collections2.java b/src/com/google/common/collect/Collections2.java new file mode 100644 index 0000000..ba4568e --- /dev/null +++ b/src/com/google/common/collect/Collections2.java @@ -0,0 +1,462 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import com.google.common.math.IntMath; +import com.google.common.math.LongMath; +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Collections2 { + static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null"); + + private Collections2() { + } + + public static Collection filter(Collection unfiltered, Predicate predicate) { + if (unfiltered instanceof FilteredCollection) { + return ((FilteredCollection)unfiltered).createCombined(predicate); + } + return new FilteredCollection(Preconditions.checkNotNull(unfiltered), Preconditions.checkNotNull(predicate)); + } + + static boolean safeContains(Collection collection, @Nullable Object object) { + Preconditions.checkNotNull(collection); + try { + return collection.contains(object); + } + catch (ClassCastException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + } + + static boolean safeRemove(Collection collection, @Nullable Object object) { + Preconditions.checkNotNull(collection); + try { + return collection.remove(object); + } + catch (ClassCastException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + } + + public static Collection transform(Collection fromCollection, Function function) { + return new TransformedCollection(fromCollection, function); + } + + static boolean containsAllImpl(Collection self, Collection c) { + return Iterables.all(c, Predicates.in(self)); + } + + static String toStringImpl(final Collection collection) { + StringBuilder sb = Collections2.newStringBuilderForCollection(collection.size()).append('['); + STANDARD_JOINER.appendTo(sb, Iterables.transform(collection, new Function(){ + + @Override + public Object apply(Object input) { + return input == collection ? "(this Collection)" : input; + } + })); + return sb.append(']').toString(); + } + + static StringBuilder newStringBuilderForCollection(int size) { + CollectPreconditions.checkNonnegative(size, "size"); + return new StringBuilder((int)Math.min((long)size * 8L, 0x40000000L)); + } + + static Collection cast(Iterable iterable) { + return (Collection)iterable; + } + + @Beta + public static > Collection> orderedPermutations(Iterable elements) { + return Collections2.orderedPermutations(elements, Ordering.natural()); + } + + @Beta + public static Collection> orderedPermutations(Iterable elements, Comparator comparator) { + return new OrderedPermutationCollection(elements, comparator); + } + + @Beta + public static Collection> permutations(Collection elements) { + return new PermutationCollection(ImmutableList.copyOf(elements)); + } + + private static boolean isPermutation(List first, List second) { + if (first.size() != second.size()) { + return false; + } + HashMultiset firstMultiset = HashMultiset.create(first); + HashMultiset secondMultiset = HashMultiset.create(second); + return firstMultiset.equals(secondMultiset); + } + + private static boolean isPositiveInt(long n) { + return n >= 0L && n <= Integer.MAX_VALUE; + } + + private static class PermutationIterator + extends AbstractIterator> { + final List list; + final int[] c; + final int[] o; + int j; + + PermutationIterator(List list) { + this.list = new ArrayList(list); + int n = list.size(); + this.c = new int[n]; + this.o = new int[n]; + Arrays.fill(this.c, 0); + Arrays.fill(this.o, 1); + this.j = Integer.MAX_VALUE; + } + + @Override + protected List computeNext() { + if (this.j <= 0) { + return (List)this.endOfData(); + } + ImmutableList next = ImmutableList.copyOf(this.list); + this.calculateNextPermutation(); + return next; + } + + void calculateNextPermutation() { + block4: { + int q; + this.j = this.list.size() - 1; + int s = 0; + if (this.j == -1) { + return; + } + while (true) { + if ((q = this.c[this.j] + this.o[this.j]) < 0) { + this.switchDirection(); + continue; + } + if (q != this.j + 1) break; + if (this.j != 0) { + ++s; + this.switchDirection(); + continue; + } + break block4; + break; + } + Collections.swap(this.list, this.j - this.c[this.j] + s, this.j - q + s); + this.c[this.j] = q; + } + } + + void switchDirection() { + this.o[this.j] = -this.o[this.j]; + --this.j; + } + } + + private static final class PermutationCollection + extends AbstractCollection> { + final ImmutableList inputList; + + PermutationCollection(ImmutableList input) { + this.inputList = input; + } + + @Override + public int size() { + return IntMath.factorial(this.inputList.size()); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Iterator> iterator() { + return new PermutationIterator(this.inputList); + } + + @Override + public boolean contains(@Nullable Object obj) { + if (obj instanceof List) { + List list = (List)obj; + return Collections2.isPermutation(this.inputList, list); + } + return false; + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.inputList)); + return new StringBuilder(14 + string.length()).append("permutations(").append(string).append(")").toString(); + } + } + + private static final class OrderedPermutationIterator + extends AbstractIterator> { + List nextPermutation; + final Comparator comparator; + + OrderedPermutationIterator(List list, Comparator comparator) { + this.nextPermutation = Lists.newArrayList(list); + this.comparator = comparator; + } + + @Override + protected List computeNext() { + if (this.nextPermutation == null) { + return (List)this.endOfData(); + } + ImmutableList next = ImmutableList.copyOf(this.nextPermutation); + this.calculateNextPermutation(); + return next; + } + + void calculateNextPermutation() { + int j = this.findNextJ(); + if (j == -1) { + this.nextPermutation = null; + return; + } + int l = this.findNextL(j); + Collections.swap(this.nextPermutation, j, l); + int n = this.nextPermutation.size(); + Collections.reverse(this.nextPermutation.subList(j + 1, n)); + } + + int findNextJ() { + for (int k = this.nextPermutation.size() - 2; k >= 0; --k) { + if (this.comparator.compare(this.nextPermutation.get(k), this.nextPermutation.get(k + 1)) >= 0) continue; + return k; + } + return -1; + } + + int findNextL(int j) { + E ak = this.nextPermutation.get(j); + for (int l = this.nextPermutation.size() - 1; l > j; --l) { + if (this.comparator.compare(ak, this.nextPermutation.get(l)) >= 0) continue; + return l; + } + throw new AssertionError((Object)"this statement should be unreachable"); + } + } + + private static final class OrderedPermutationCollection + extends AbstractCollection> { + final ImmutableList inputList; + final Comparator comparator; + final int size; + + OrderedPermutationCollection(Iterable input, Comparator comparator) { + this.inputList = Ordering.from(comparator).immutableSortedCopy(input); + this.comparator = comparator; + this.size = OrderedPermutationCollection.calculateSize(this.inputList, comparator); + } + + private static int calculateSize(List sortedInputList, Comparator comparator) { + long permutations = 1L; + int n = 1; + int r = 1; + while (n < sortedInputList.size()) { + int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n)); + if (comparison < 0) { + permutations *= LongMath.binomial(n, r); + r = 0; + if (!Collections2.isPositiveInt(permutations)) { + return Integer.MAX_VALUE; + } + } + ++n; + ++r; + } + if (!Collections2.isPositiveInt(permutations *= LongMath.binomial(n, r))) { + return Integer.MAX_VALUE; + } + return (int)permutations; + } + + @Override + public int size() { + return this.size; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Iterator> iterator() { + return new OrderedPermutationIterator(this.inputList, this.comparator); + } + + @Override + public boolean contains(@Nullable Object obj) { + if (obj instanceof List) { + List list = (List)obj; + return Collections2.isPermutation(this.inputList, list); + } + return false; + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.inputList)); + return new StringBuilder(30 + string.length()).append("orderedPermutationCollection(").append(string).append(")").toString(); + } + } + + static class TransformedCollection + extends AbstractCollection { + final Collection fromCollection; + final Function function; + + TransformedCollection(Collection fromCollection, Function function) { + this.fromCollection = Preconditions.checkNotNull(fromCollection); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public void clear() { + this.fromCollection.clear(); + } + + @Override + public boolean isEmpty() { + return this.fromCollection.isEmpty(); + } + + @Override + public Iterator iterator() { + return Iterators.transform(this.fromCollection.iterator(), this.function); + } + + @Override + public int size() { + return this.fromCollection.size(); + } + } + + static class FilteredCollection + extends AbstractCollection { + final Collection unfiltered; + final Predicate predicate; + + FilteredCollection(Collection unfiltered, Predicate predicate) { + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + FilteredCollection createCombined(Predicate newPredicate) { + return new FilteredCollection(this.unfiltered, Predicates.and(this.predicate, newPredicate)); + } + + @Override + public boolean add(E element) { + Preconditions.checkArgument(this.predicate.apply(element)); + return this.unfiltered.add(element); + } + + @Override + public boolean addAll(Collection collection) { + for (E element : collection) { + Preconditions.checkArgument(this.predicate.apply(element)); + } + return this.unfiltered.addAll(collection); + } + + @Override + public void clear() { + Iterables.removeIf(this.unfiltered, this.predicate); + } + + @Override + public boolean contains(@Nullable Object element) { + if (Collections2.safeContains(this.unfiltered, element)) { + Object e = element; + return this.predicate.apply(e); + } + return false; + } + + @Override + public boolean containsAll(Collection collection) { + return Collections2.containsAllImpl(this, collection); + } + + @Override + public boolean isEmpty() { + return !Iterables.any(this.unfiltered, this.predicate); + } + + @Override + public Iterator iterator() { + return Iterators.filter(this.unfiltered.iterator(), this.predicate); + } + + @Override + public boolean remove(Object element) { + return this.contains(element) && this.unfiltered.remove(element); + } + + @Override + public boolean removeAll(Collection collection) { + return Iterables.removeIf(this.unfiltered, Predicates.and(this.predicate, Predicates.in(collection))); + } + + @Override + public boolean retainAll(Collection collection) { + return Iterables.removeIf(this.unfiltered, Predicates.and(this.predicate, Predicates.not(Predicates.in(collection)))); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + + @Override + public Object[] toArray() { + return Lists.newArrayList(this.iterator()).toArray(); + } + + @Override + public T[] toArray(T[] array) { + return Lists.newArrayList(this.iterator()).toArray(array); + } + } +} diff --git a/src/com/google/common/collect/ComparatorOrdering.java b/src/com/google/common/collect/ComparatorOrdering.java new file mode 100644 index 0000000..ea17e9d --- /dev/null +++ b/src/com/google/common/collect/ComparatorOrdering.java @@ -0,0 +1,48 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Comparator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class ComparatorOrdering +extends Ordering +implements Serializable { + final Comparator comparator; + private static final long serialVersionUID = 0L; + + ComparatorOrdering(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + @Override + public int compare(T a, T b) { + return this.comparator.compare(a, b); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof ComparatorOrdering) { + ComparatorOrdering that = (ComparatorOrdering)object; + return this.comparator.equals(that.comparator); + } + return false; + } + + public int hashCode() { + return this.comparator.hashCode(); + } + + public String toString() { + return this.comparator.toString(); + } +} diff --git a/src/com/google/common/collect/ComparisonChain.java b/src/com/google/common/collect/ComparisonChain.java new file mode 100644 index 0000000..f6916bf --- /dev/null +++ b/src/com/google/common/collect/ComparisonChain.java @@ -0,0 +1,145 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.primitives.Booleans; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.util.Comparator; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ComparisonChain { + private static final ComparisonChain ACTIVE = new ComparisonChain(){ + + public ComparisonChain compare(Comparable left, Comparable right) { + return this.classify(left.compareTo(right)); + } + + @Override + public ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator comparator) { + return this.classify(comparator.compare(left, right)); + } + + @Override + public ComparisonChain compare(int left, int right) { + return this.classify(Ints.compare(left, right)); + } + + @Override + public ComparisonChain compare(long left, long right) { + return this.classify(Longs.compare(left, right)); + } + + @Override + public ComparisonChain compare(float left, float right) { + return this.classify(Float.compare(left, right)); + } + + @Override + public ComparisonChain compare(double left, double right) { + return this.classify(Double.compare(left, right)); + } + + @Override + public ComparisonChain compareTrueFirst(boolean left, boolean right) { + return this.classify(Booleans.compare(right, left)); + } + + @Override + public ComparisonChain compareFalseFirst(boolean left, boolean right) { + return this.classify(Booleans.compare(left, right)); + } + + ComparisonChain classify(int result) { + return result < 0 ? LESS : (result > 0 ? GREATER : ACTIVE); + } + + @Override + public int result() { + return 0; + } + }; + private static final ComparisonChain LESS = new InactiveComparisonChain(-1); + private static final ComparisonChain GREATER = new InactiveComparisonChain(1); + + private ComparisonChain() { + } + + public static ComparisonChain start() { + return ACTIVE; + } + + public abstract ComparisonChain compare(Comparable var1, Comparable var2); + + public abstract ComparisonChain compare(@Nullable T var1, @Nullable T var2, Comparator var3); + + public abstract ComparisonChain compare(int var1, int var2); + + public abstract ComparisonChain compare(long var1, long var3); + + public abstract ComparisonChain compare(float var1, float var2); + + public abstract ComparisonChain compare(double var1, double var3); + + public abstract ComparisonChain compareTrueFirst(boolean var1, boolean var2); + + public abstract ComparisonChain compareFalseFirst(boolean var1, boolean var2); + + public abstract int result(); + + private static final class InactiveComparisonChain + extends ComparisonChain { + final int result; + + InactiveComparisonChain(int result) { + this.result = result; + } + + public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) { + return this; + } + + @Override + public ComparisonChain compare(@Nullable T left, @Nullable T right, @Nullable Comparator comparator) { + return this; + } + + @Override + public ComparisonChain compare(int left, int right) { + return this; + } + + @Override + public ComparisonChain compare(long left, long right) { + return this; + } + + @Override + public ComparisonChain compare(float left, float right) { + return this; + } + + @Override + public ComparisonChain compare(double left, double right) { + return this; + } + + @Override + public ComparisonChain compareTrueFirst(boolean left, boolean right) { + return this; + } + + @Override + public ComparisonChain compareFalseFirst(boolean left, boolean right) { + return this; + } + + @Override + public int result() { + return this.result; + } + } +} diff --git a/src/com/google/common/collect/CompoundOrdering.java b/src/com/google/common/collect/CompoundOrdering.java new file mode 100644 index 0000000..1f79679 --- /dev/null +++ b/src/com/google/common/collect/CompoundOrdering.java @@ -0,0 +1,58 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Comparator; + +@GwtCompatible(serializable=true) +final class CompoundOrdering +extends Ordering +implements Serializable { + final ImmutableList> comparators; + private static final long serialVersionUID = 0L; + + CompoundOrdering(Comparator primary, Comparator secondary) { + this.comparators = ImmutableList.of(primary, secondary); + } + + CompoundOrdering(Iterable> comparators) { + this.comparators = ImmutableList.copyOf(comparators); + } + + @Override + public int compare(T left, T right) { + int size = this.comparators.size(); + for (int i = 0; i < size; ++i) { + int result = ((Comparator)this.comparators.get(i)).compare(left, right); + if (result == 0) continue; + return result; + } + return 0; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof CompoundOrdering) { + CompoundOrdering that = (CompoundOrdering)object; + return this.comparators.equals(that.comparators); + } + return false; + } + + public int hashCode() { + return this.comparators.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.comparators)); + return new StringBuilder(19 + string.length()).append("Ordering.compound(").append(string).append(")").toString(); + } +} diff --git a/src/com/google/common/collect/ComputationException.java b/src/com/google/common/collect/ComputationException.java new file mode 100644 index 0000000..e028ae3 --- /dev/null +++ b/src/com/google/common/collect/ComputationException.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public class ComputationException +extends RuntimeException { + private static final long serialVersionUID = 0L; + + public ComputationException(@Nullable Throwable cause) { + super(cause); + } +} diff --git a/src/com/google/common/collect/ComputingConcurrentHashMap.java b/src/com/google/common/collect/ComputingConcurrentHashMap.java new file mode 100644 index 0000000..1b442d9 --- /dev/null +++ b/src/com/google/common/collect/ComputingConcurrentHashMap.java @@ -0,0 +1,365 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.MapMaker; +import com.google.common.collect.MapMakerInternalMap; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.ref.ReferenceQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicReferenceArray; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + +class ComputingConcurrentHashMap +extends MapMakerInternalMap { + final Function computingFunction; + private static final long serialVersionUID = 4L; + + ComputingConcurrentHashMap(MapMaker builder, Function computingFunction) { + super(builder); + this.computingFunction = Preconditions.checkNotNull(computingFunction); + } + + @Override + MapMakerInternalMap.Segment createSegment(int initialCapacity, int maxSegmentSize) { + return new ComputingSegment(this, initialCapacity, maxSegmentSize); + } + + @Override + ComputingSegment segmentFor(int hash) { + return (ComputingSegment)super.segmentFor(hash); + } + + V getOrCompute(K key) throws ExecutionException { + int hash = this.hash(Preconditions.checkNotNull(key)); + return ((ComputingSegment)this.segmentFor(hash)).getOrCompute(key, hash, this.computingFunction); + } + + @Override + Object writeReplace() { + return new ComputingSerializationProxy(this.keyStrength, this.valueStrength, this.keyEquivalence, this.valueEquivalence, this.expireAfterWriteNanos, this.expireAfterAccessNanos, this.maximumSize, this.concurrencyLevel, this.removalListener, this, this.computingFunction); + } + + static final class ComputingSerializationProxy + extends MapMakerInternalMap.AbstractSerializationProxy { + final Function computingFunction; + private static final long serialVersionUID = 4L; + + ComputingSerializationProxy(MapMakerInternalMap.Strength keyStrength, MapMakerInternalMap.Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate, Function computingFunction) { + super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate); + this.computingFunction = computingFunction; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + this.writeMapTo(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + MapMaker mapMaker = this.readMapMaker(in); + this.delegate = mapMaker.makeComputingMap(this.computingFunction); + this.readEntries(in); + } + + Object readResolve() { + return this.delegate; + } + } + + private static final class ComputingValueReference + implements MapMakerInternalMap.ValueReference { + final Function computingFunction; + @GuardedBy(value="ComputingValueReference.this") + volatile MapMakerInternalMap.ValueReference computedReference = MapMakerInternalMap.unset(); + + public ComputingValueReference(Function computingFunction) { + this.computingFunction = computingFunction; + } + + @Override + public V get() { + return null; + } + + @Override + public MapMakerInternalMap.ReferenceEntry getEntry() { + return null; + } + + @Override + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, @Nullable V value, MapMakerInternalMap.ReferenceEntry entry) { + return this; + } + + @Override + public boolean isComputingReference() { + return true; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V waitForValue() throws ExecutionException { + if (this.computedReference == MapMakerInternalMap.UNSET) { + boolean interrupted = false; + try { + ComputingValueReference computingValueReference = this; + synchronized (computingValueReference) { + while (this.computedReference == MapMakerInternalMap.UNSET) { + try { + this.wait(); + } + catch (InterruptedException ie) { + interrupted = true; + } + } + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + return this.computedReference.waitForValue(); + } + + @Override + public void clear(MapMakerInternalMap.ValueReference newValue) { + this.setValueReference(newValue); + } + + V compute(K key, int hash) throws ExecutionException { + V value; + try { + value = this.computingFunction.apply(key); + } + catch (Throwable t) { + this.setValueReference(new ComputationExceptionReference(t)); + throw new ExecutionException(t); + } + this.setValueReference(new ComputedReference(value)); + return value; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void setValueReference(MapMakerInternalMap.ValueReference valueReference) { + ComputingValueReference computingValueReference = this; + synchronized (computingValueReference) { + if (this.computedReference == MapMakerInternalMap.UNSET) { + this.computedReference = valueReference; + this.notifyAll(); + } + } + } + } + + private static final class ComputedReference + implements MapMakerInternalMap.ValueReference { + final V value; + + ComputedReference(@Nullable V value) { + this.value = value; + } + + @Override + public V get() { + return this.value; + } + + @Override + public MapMakerInternalMap.ReferenceEntry getEntry() { + return null; + } + + @Override + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) { + return this; + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public V waitForValue() { + return this.get(); + } + + @Override + public void clear(MapMakerInternalMap.ValueReference newValue) { + } + } + + private static final class ComputationExceptionReference + implements MapMakerInternalMap.ValueReference { + final Throwable t; + + ComputationExceptionReference(Throwable t) { + this.t = t; + } + + @Override + public V get() { + return null; + } + + @Override + public MapMakerInternalMap.ReferenceEntry getEntry() { + return null; + } + + @Override + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) { + return this; + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public V waitForValue() throws ExecutionException { + throw new ExecutionException(this.t); + } + + @Override + public void clear(MapMakerInternalMap.ValueReference newValue) { + } + } + + static final class ComputingSegment + extends MapMakerInternalMap.Segment { + ComputingSegment(MapMakerInternalMap map, int initialCapacity, int maxSegmentSize) { + super(map, initialCapacity, maxSegmentSize); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + * Enabled aggressive block sorting + * Enabled unnecessary exception pruning + * Enabled aggressive exception aggregation + */ + V getOrCompute(K key, int hash, Function computingFunction) throws ExecutionException { + try { + Object v; + MapMakerInternalMap.ReferenceEntry e; + Object value; + do { + if ((e = this.getEntry(key, hash)) != null && (value = this.getLiveValue(e)) != null) { + this.recordRead(e); + v = value; + return v; + } + if (e == null || !e.getValueReference().isComputingReference()) { + ComputingValueReference computingValueReference; + boolean createNewEntry; + block22: { + createNewEntry = true; + computingValueReference = null; + this.lock(); + try { + MapMakerInternalMap.ReferenceEntry first; + this.preWriteCleanup(); + int newCount = this.count - 1; + AtomicReferenceArray table = this.table; + int index = hash & table.length() - 1; + for (e = first = (MapMakerInternalMap.ReferenceEntry)table.get(index); e != null; e = e.getNext()) { + Object entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + if (valueReference.isComputingReference()) { + createNewEntry = false; + break; + } + Object value2 = e.getValueReference().get(); + if (value2 == null) { + this.enqueueNotification(entryKey, hash, value2, MapMaker.RemovalCause.COLLECTED); + } else if (this.map.expires() && this.map.isExpired(e)) { + this.enqueueNotification(entryKey, hash, value2, MapMaker.RemovalCause.EXPIRED); + } else { + this.recordLockedRead(e); + Object v2 = value2; + return v2; + } + this.evictionQueue.remove(e); + this.expirationQueue.remove(e); + this.count = newCount; + break; + } + if (!createNewEntry) break block22; + computingValueReference = new ComputingValueReference(computingFunction); + if (e == null) { + e = this.newEntry(key, hash, first); + e.setValueReference(computingValueReference); + table.set(index, e); + } else { + e.setValueReference(computingValueReference); + } + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + if (createNewEntry) { + V v3 = this.compute(key, hash, e, computingValueReference); + return v3; + } + } + Preconditions.checkState(!Thread.holdsLock(e), "Recursive computation"); + } while ((value = e.getValueReference().waitForValue()) == null); + this.recordRead(e); + v = value; + return v; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V compute(K key, int hash, MapMakerInternalMap.ReferenceEntry e, ComputingValueReference computingValueReference) throws ExecutionException { + Object value = null; + long start = System.nanoTime(); + long end = 0L; + try { + Object oldValue; + MapMakerInternalMap.ReferenceEntry referenceEntry = e; + synchronized (referenceEntry) { + value = computingValueReference.compute(key, hash); + end = System.nanoTime(); + } + if (value != null && (oldValue = this.put(key, hash, value, true)) != null) { + this.enqueueNotification(key, hash, value, MapMaker.RemovalCause.REPLACED); + } + referenceEntry = value; + return (V)referenceEntry; + } + finally { + if (end == 0L) { + end = System.nanoTime(); + } + if (value == null) { + this.clearValue(key, hash, computingValueReference); + } + } + } + } +} diff --git a/src/com/google/common/collect/ConcurrentHashMultiset.java b/src/com/google/common/collect/ConcurrentHashMultiset.java new file mode 100644 index 0000000..1dfb007 --- /dev/null +++ b/src/com/google/common/collect/ConcurrentHashMultiset.java @@ -0,0 +1,383 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractMultiset; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingIterator; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Serialization; +import com.google.common.math.IntMath; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + +public final class ConcurrentHashMultiset +extends AbstractMultiset +implements Serializable { + private final transient ConcurrentMap countMap; + private static final long serialVersionUID = 1L; + + public static ConcurrentHashMultiset create() { + return new ConcurrentHashMultiset(new ConcurrentHashMap()); + } + + public static ConcurrentHashMultiset create(Iterable elements) { + ConcurrentHashMultiset multiset = ConcurrentHashMultiset.create(); + Iterables.addAll(multiset, elements); + return multiset; + } + + @Beta + public static ConcurrentHashMultiset create(MapMaker mapMaker) { + return new ConcurrentHashMultiset(mapMaker.makeMap()); + } + + @VisibleForTesting + ConcurrentHashMultiset(ConcurrentMap countMap) { + Preconditions.checkArgument(countMap.isEmpty()); + this.countMap = countMap; + } + + @Override + public int count(@Nullable Object element) { + AtomicInteger existingCounter = Maps.safeGet(this.countMap, element); + return existingCounter == null ? 0 : existingCounter.get(); + } + + @Override + public int size() { + long sum = 0L; + for (AtomicInteger value : this.countMap.values()) { + sum += (long)value.get(); + } + return Ints.saturatedCast(sum); + } + + @Override + public Object[] toArray() { + return this.snapshot().toArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.snapshot().toArray(array); + } + + private List snapshot() { + ArrayList list = Lists.newArrayListWithExpectedSize(this.size()); + for (Multiset.Entry entry : this.entrySet()) { + Object element = entry.getElement(); + for (int i = entry.getCount(); i > 0; --i) { + list.add(element); + } + } + return list; + } + + @Override + public int add(E element, int occurrences) { + AtomicInteger existingCounter; + AtomicInteger newCounter; + Preconditions.checkNotNull(element); + if (occurrences == 0) { + return this.count(element); + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences); + do { + int oldValue; + if ((existingCounter = Maps.safeGet(this.countMap, element)) == null && (existingCounter = this.countMap.putIfAbsent(element, new AtomicInteger(occurrences))) == null) { + return 0; + } + while ((oldValue = existingCounter.get()) != 0) { + try { + int newValue = IntMath.checkedAdd(oldValue, occurrences); + if (!existingCounter.compareAndSet(oldValue, newValue)) continue; + return oldValue; + } + catch (ArithmeticException overflow) { + int n = occurrences; + int n2 = oldValue; + throw new IllegalArgumentException(new StringBuilder(65).append("Overflow adding ").append(n).append(" occurrences to a count of ").append(n2).toString()); + } + } + } while (this.countMap.putIfAbsent(element, newCounter = new AtomicInteger(occurrences)) != null && !this.countMap.replace(element, existingCounter, newCounter)); + return 0; + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + int oldValue; + if (occurrences == 0) { + return this.count(element); + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences); + AtomicInteger existingCounter = Maps.safeGet(this.countMap, element); + if (existingCounter == null) { + return 0; + } + while ((oldValue = existingCounter.get()) != 0) { + int newValue = Math.max(0, oldValue - occurrences); + if (!existingCounter.compareAndSet(oldValue, newValue)) continue; + if (newValue == 0) { + this.countMap.remove(element, existingCounter); + } + return oldValue; + } + return 0; + } + + public boolean removeExactly(@Nullable Object element, int occurrences) { + int newValue; + int oldValue; + if (occurrences == 0) { + return true; + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences); + AtomicInteger existingCounter = Maps.safeGet(this.countMap, element); + if (existingCounter == null) { + return false; + } + do { + if ((oldValue = existingCounter.get()) >= occurrences) continue; + return false; + } while (!existingCounter.compareAndSet(oldValue, newValue = oldValue - occurrences)); + if (newValue == 0) { + this.countMap.remove(element, existingCounter); + } + return true; + } + + @Override + public int setCount(E element, int count) { + int oldValue; + AtomicInteger existingCounter; + Preconditions.checkNotNull(element); + CollectPreconditions.checkNonnegative(count, "count"); + block0: while (true) { + if ((existingCounter = Maps.safeGet(this.countMap, element)) == null) { + if (count == 0) { + return 0; + } + existingCounter = this.countMap.putIfAbsent(element, new AtomicInteger(count)); + if (existingCounter == null) { + return 0; + } + } + do { + if ((oldValue = existingCounter.get()) != 0) continue; + if (count == 0) { + return 0; + } + AtomicInteger newCounter = new AtomicInteger(count); + if (this.countMap.putIfAbsent(element, newCounter) != null && !this.countMap.replace(element, existingCounter, newCounter)) continue block0; + return 0; + } while (!existingCounter.compareAndSet(oldValue, count)); + break; + } + if (count == 0) { + this.countMap.remove(element, existingCounter); + } + return oldValue; + } + + @Override + public boolean setCount(E element, int expectedOldCount, int newCount) { + Preconditions.checkNotNull(element); + CollectPreconditions.checkNonnegative(expectedOldCount, "oldCount"); + CollectPreconditions.checkNonnegative(newCount, "newCount"); + AtomicInteger existingCounter = Maps.safeGet(this.countMap, element); + if (existingCounter == null) { + if (expectedOldCount != 0) { + return false; + } + if (newCount == 0) { + return true; + } + return this.countMap.putIfAbsent(element, new AtomicInteger(newCount)) == null; + } + int oldValue = existingCounter.get(); + if (oldValue == expectedOldCount) { + if (oldValue == 0) { + if (newCount == 0) { + this.countMap.remove(element, existingCounter); + return true; + } + AtomicInteger newCounter = new AtomicInteger(newCount); + return this.countMap.putIfAbsent(element, newCounter) == null || this.countMap.replace(element, existingCounter, newCounter); + } + if (existingCounter.compareAndSet(oldValue, newCount)) { + if (newCount == 0) { + this.countMap.remove(element, existingCounter); + } + return true; + } + } + return false; + } + + @Override + Set createElementSet() { + final Set delegate = this.countMap.keySet(); + return new ForwardingSet(){ + + @Override + protected Set delegate() { + return delegate; + } + + @Override + public boolean contains(@Nullable Object object) { + return object != null && Collections2.safeContains(delegate, object); + } + + @Override + public boolean containsAll(Collection collection) { + return this.standardContainsAll(collection); + } + + @Override + public boolean remove(Object object) { + return object != null && Collections2.safeRemove(delegate, object); + } + + @Override + public boolean removeAll(Collection c) { + return this.standardRemoveAll(c); + } + }; + } + + @Override + public Set> createEntrySet() { + return new EntrySet(); + } + + @Override + int distinctElements() { + return this.countMap.size(); + } + + @Override + public boolean isEmpty() { + return this.countMap.isEmpty(); + } + + @Override + Iterator> entryIterator() { + final AbstractIterator readOnlyIterator = new AbstractIterator>(){ + private Iterator> mapEntries; + { + this.mapEntries = ConcurrentHashMultiset.this.countMap.entrySet().iterator(); + } + + @Override + protected Multiset.Entry computeNext() { + Map.Entry mapEntry; + int count; + do { + if (this.mapEntries.hasNext()) continue; + return (Multiset.Entry)this.endOfData(); + } while ((count = (mapEntry = this.mapEntries.next()).getValue().get()) == 0); + return Multisets.immutableEntry(mapEntry.getKey(), count); + } + }; + return new ForwardingIterator>(){ + private Multiset.Entry last; + + @Override + protected Iterator> delegate() { + return readOnlyIterator; + } + + @Override + public Multiset.Entry next() { + this.last = (Multiset.Entry)super.next(); + return this.last; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.last != null); + ConcurrentHashMultiset.this.setCount(this.last.getElement(), 0); + this.last = null; + } + }; + } + + @Override + public void clear() { + this.countMap.clear(); + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.countMap); + } + + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + ConcurrentMap deserializedCountMap = (ConcurrentMap)stream.readObject(); + FieldSettersHolder.COUNT_MAP_FIELD_SETTER.set(this, deserializedCountMap); + } + + private class EntrySet + extends AbstractMultiset.EntrySet { + private EntrySet() { + super(ConcurrentHashMultiset.this); + } + + @Override + ConcurrentHashMultiset multiset() { + return ConcurrentHashMultiset.this; + } + + @Override + public Object[] toArray() { + return this.snapshot().toArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.snapshot().toArray(array); + } + + private List> snapshot() { + ArrayList list = Lists.newArrayListWithExpectedSize(this.size()); + Iterators.addAll(list, this.iterator()); + return list; + } + } + + private static class FieldSettersHolder { + static final Serialization.FieldSetter COUNT_MAP_FIELD_SETTER = Serialization.getFieldSetter(ConcurrentHashMultiset.class, "countMap"); + + private FieldSettersHolder() { + } + } +} diff --git a/src/com/google/common/collect/Constraint.java b/src/com/google/common/collect/Constraint.java new file mode 100644 index 0000000..f4325ad --- /dev/null +++ b/src/com/google/common/collect/Constraint.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +interface Constraint { + public E checkElement(E var1); + + public String toString(); +} diff --git a/src/com/google/common/collect/Constraints.java b/src/com/google/common/collect/Constraints.java new file mode 100644 index 0000000..7e56aa6 --- /dev/null +++ b/src/com/google/common/collect/Constraints.java @@ -0,0 +1,260 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Constraint; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingList; +import com.google.common.collect.ForwardingListIterator; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ForwardingSortedSet; +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedSet; + +@GwtCompatible +final class Constraints { + private Constraints() { + } + + public static Collection constrainedCollection(Collection collection, Constraint constraint) { + return new ConstrainedCollection(collection, constraint); + } + + public static Set constrainedSet(Set set, Constraint constraint) { + return new ConstrainedSet(set, constraint); + } + + public static SortedSet constrainedSortedSet(SortedSet sortedSet, Constraint constraint) { + return new ConstrainedSortedSet(sortedSet, constraint); + } + + public static List constrainedList(List list, Constraint constraint) { + return list instanceof RandomAccess ? new ConstrainedRandomAccessList(list, constraint) : new ConstrainedList(list, constraint); + } + + private static ListIterator constrainedListIterator(ListIterator listIterator, Constraint constraint) { + return new ConstrainedListIterator(listIterator, constraint); + } + + static Collection constrainedTypePreservingCollection(Collection collection, Constraint constraint) { + if (collection instanceof SortedSet) { + return Constraints.constrainedSortedSet((SortedSet)collection, constraint); + } + if (collection instanceof Set) { + return Constraints.constrainedSet((Set)collection, constraint); + } + if (collection instanceof List) { + return Constraints.constrainedList((List)collection, constraint); + } + return Constraints.constrainedCollection(collection, constraint); + } + + private static Collection checkElements(Collection elements, Constraint constraint) { + ArrayList copy = Lists.newArrayList(elements); + for (Object element : copy) { + constraint.checkElement(element); + } + return copy; + } + + static class ConstrainedListIterator + extends ForwardingListIterator { + private final ListIterator delegate; + private final Constraint constraint; + + public ConstrainedListIterator(ListIterator delegate, Constraint constraint) { + this.delegate = delegate; + this.constraint = constraint; + } + + @Override + protected ListIterator delegate() { + return this.delegate; + } + + @Override + public void add(E element) { + this.constraint.checkElement(element); + this.delegate.add(element); + } + + @Override + public void set(E element) { + this.constraint.checkElement(element); + this.delegate.set(element); + } + } + + static class ConstrainedRandomAccessList + extends ConstrainedList + implements RandomAccess { + ConstrainedRandomAccessList(List delegate, Constraint constraint) { + super(delegate, constraint); + } + } + + @GwtCompatible + private static class ConstrainedList + extends ForwardingList { + final List delegate; + final Constraint constraint; + + ConstrainedList(List delegate, Constraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected List delegate() { + return this.delegate; + } + + @Override + public boolean add(E element) { + this.constraint.checkElement(element); + return this.delegate.add(element); + } + + @Override + public void add(int index, E element) { + this.constraint.checkElement(element); + this.delegate.add(index, element); + } + + @Override + public boolean addAll(Collection elements) { + return this.delegate.addAll(Constraints.checkElements(elements, this.constraint)); + } + + @Override + public boolean addAll(int index, Collection elements) { + return this.delegate.addAll(index, Constraints.checkElements(elements, this.constraint)); + } + + @Override + public ListIterator listIterator() { + return Constraints.constrainedListIterator(this.delegate.listIterator(), this.constraint); + } + + @Override + public ListIterator listIterator(int index) { + return Constraints.constrainedListIterator(this.delegate.listIterator(index), this.constraint); + } + + @Override + public E set(int index, E element) { + this.constraint.checkElement(element); + return this.delegate.set(index, element); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return Constraints.constrainedList(this.delegate.subList(fromIndex, toIndex), this.constraint); + } + } + + private static class ConstrainedSortedSet + extends ForwardingSortedSet { + final SortedSet delegate; + final Constraint constraint; + + ConstrainedSortedSet(SortedSet delegate, Constraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected SortedSet delegate() { + return this.delegate; + } + + @Override + public SortedSet headSet(E toElement) { + return Constraints.constrainedSortedSet(this.delegate.headSet(toElement), this.constraint); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return Constraints.constrainedSortedSet(this.delegate.subSet(fromElement, toElement), this.constraint); + } + + @Override + public SortedSet tailSet(E fromElement) { + return Constraints.constrainedSortedSet(this.delegate.tailSet(fromElement), this.constraint); + } + + @Override + public boolean add(E element) { + this.constraint.checkElement(element); + return this.delegate.add(element); + } + + @Override + public boolean addAll(Collection elements) { + return this.delegate.addAll(Constraints.checkElements(elements, this.constraint)); + } + } + + static class ConstrainedSet + extends ForwardingSet { + private final Set delegate; + private final Constraint constraint; + + public ConstrainedSet(Set delegate, Constraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected Set delegate() { + return this.delegate; + } + + @Override + public boolean add(E element) { + this.constraint.checkElement(element); + return this.delegate.add(element); + } + + @Override + public boolean addAll(Collection elements) { + return this.delegate.addAll(Constraints.checkElements(elements, this.constraint)); + } + } + + static class ConstrainedCollection + extends ForwardingCollection { + private final Collection delegate; + private final Constraint constraint; + + public ConstrainedCollection(Collection delegate, Constraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected Collection delegate() { + return this.delegate; + } + + @Override + public boolean add(E element) { + this.constraint.checkElement(element); + return this.delegate.add(element); + } + + @Override + public boolean addAll(Collection elements) { + return this.delegate.addAll(Constraints.checkElements(elements, this.constraint)); + } + } +} diff --git a/src/com/google/common/collect/ContiguousSet.java b/src/com/google/common/collect/ContiguousSet.java new file mode 100644 index 0000000..aa09538 --- /dev/null +++ b/src/com/google/common/collect/ContiguousSet.java @@ -0,0 +1,112 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.EmptyContiguousSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import com.google.common.collect.Range; +import com.google.common.collect.RegularContiguousSet; +import java.util.NoSuchElementException; + +@Beta +@GwtCompatible(emulated=true) +public abstract class ContiguousSet +extends ImmutableSortedSet { + final DiscreteDomain domain; + + public static ContiguousSet create(Range range, DiscreteDomain domain) { + Preconditions.checkNotNull(range); + Preconditions.checkNotNull(domain); + Range effectiveRange = range; + try { + if (!range.hasLowerBound()) { + effectiveRange = effectiveRange.intersection(Range.atLeast(domain.minValue())); + } + if (!range.hasUpperBound()) { + effectiveRange = effectiveRange.intersection(Range.atMost(domain.maxValue())); + } + } + catch (NoSuchElementException e) { + throw new IllegalArgumentException(e); + } + boolean empty = effectiveRange.isEmpty() || Range.compareOrThrow(range.lowerBound.leastValueAbove(domain), range.upperBound.greatestValueBelow(domain)) > 0; + return empty ? new EmptyContiguousSet(domain) : new RegularContiguousSet(effectiveRange, domain); + } + + ContiguousSet(DiscreteDomain domain) { + super(Ordering.natural()); + this.domain = domain; + } + + @Override + public ContiguousSet headSet(C toElement) { + return this.headSetImpl((C)((Comparable)Preconditions.checkNotNull(toElement)), false); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ContiguousSet headSet(C toElement, boolean inclusive) { + return this.headSetImpl((C)((Comparable)Preconditions.checkNotNull(toElement)), inclusive); + } + + @Override + public ContiguousSet subSet(C fromElement, C toElement) { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(this.comparator().compare(fromElement, toElement) <= 0); + return this.subSetImpl(fromElement, true, toElement, false); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ContiguousSet subSet(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(this.comparator().compare(fromElement, toElement) <= 0); + return this.subSetImpl(fromElement, fromInclusive, toElement, toInclusive); + } + + @Override + public ContiguousSet tailSet(C fromElement) { + return this.tailSetImpl((C)((Comparable)Preconditions.checkNotNull(fromElement)), true); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ContiguousSet tailSet(C fromElement, boolean inclusive) { + return this.tailSetImpl((C)((Comparable)Preconditions.checkNotNull(fromElement)), inclusive); + } + + @Override + abstract ContiguousSet headSetImpl(C var1, boolean var2); + + @Override + abstract ContiguousSet subSetImpl(C var1, boolean var2, C var3, boolean var4); + + @Override + abstract ContiguousSet tailSetImpl(C var1, boolean var2); + + public abstract ContiguousSet intersection(ContiguousSet var1); + + public abstract Range range(); + + public abstract Range range(BoundType var1, BoundType var2); + + @Override + public String toString() { + return this.range().toString(); + } + + @Deprecated + public static ImmutableSortedSet.Builder builder() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/Count.java b/src/com/google/common/collect/Count.java new file mode 100644 index 0000000..c55aafa --- /dev/null +++ b/src/com/google/common/collect/Count.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible +final class Count +implements Serializable { + private int value; + + Count(int value) { + this.value = value; + } + + public int get() { + return this.value; + } + + public int getAndAdd(int delta) { + int result = this.value; + this.value = result + delta; + return result; + } + + public int addAndGet(int delta) { + return this.value += delta; + } + + public void set(int newValue) { + this.value = newValue; + } + + public int getAndSet(int newValue) { + int result = this.value; + this.value = newValue; + return result; + } + + public int hashCode() { + return this.value; + } + + public boolean equals(@Nullable Object obj) { + return obj instanceof Count && ((Count)obj).value == this.value; + } + + public String toString() { + return Integer.toString(this.value); + } +} diff --git a/src/com/google/common/collect/Cut.java b/src/com/google/common/collect/Cut.java new file mode 100644 index 0000000..024234e --- /dev/null +++ b/src/com/google/common/collect/Cut.java @@ -0,0 +1,421 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.Range; +import com.google.common.primitives.Booleans; +import java.io.Serializable; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class Cut +implements Comparable>, +Serializable { + final C endpoint; + private static final long serialVersionUID = 0L; + + Cut(@Nullable C endpoint) { + this.endpoint = endpoint; + } + + abstract boolean isLessThan(C var1); + + abstract BoundType typeAsLowerBound(); + + abstract BoundType typeAsUpperBound(); + + abstract Cut withLowerBoundType(BoundType var1, DiscreteDomain var2); + + abstract Cut withUpperBoundType(BoundType var1, DiscreteDomain var2); + + abstract void describeAsLowerBound(StringBuilder var1); + + abstract void describeAsUpperBound(StringBuilder var1); + + abstract C leastValueAbove(DiscreteDomain var1); + + abstract C greatestValueBelow(DiscreteDomain var1); + + Cut canonical(DiscreteDomain domain) { + return this; + } + + @Override + public int compareTo(Cut that) { + if (that == Cut.belowAll()) { + return 1; + } + if (that == Cut.aboveAll()) { + return -1; + } + int result = Range.compareOrThrow(this.endpoint, that.endpoint); + if (result != 0) { + return result; + } + return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue); + } + + C endpoint() { + return this.endpoint; + } + + public boolean equals(Object obj) { + if (obj instanceof Cut) { + Cut that = (Cut)obj; + try { + int compareResult = this.compareTo(that); + return compareResult == 0; + } + catch (ClassCastException classCastException) { + // empty catch block + } + } + return false; + } + + static Cut belowAll() { + return BelowAll.INSTANCE; + } + + static Cut aboveAll() { + return AboveAll.INSTANCE; + } + + static Cut belowValue(C endpoint) { + return new BelowValue(endpoint); + } + + static Cut aboveValue(C endpoint) { + return new AboveValue(endpoint); + } + + private static final class AboveValue + extends Cut { + private static final long serialVersionUID = 0L; + + AboveValue(C endpoint) { + super((Comparable)Preconditions.checkNotNull(endpoint)); + } + + @Override + boolean isLessThan(C value) { + return Range.compareOrThrow(this.endpoint, value) < 0; + } + + @Override + BoundType typeAsLowerBound() { + return BoundType.OPEN; + } + + @Override + BoundType typeAsUpperBound() { + return BoundType.CLOSED; + } + + @Override + Cut withLowerBoundType(BoundType boundType, DiscreteDomain domain) { + switch (boundType) { + case OPEN: { + return this; + } + case CLOSED: { + Comparable next = domain.next(this.endpoint); + return next == null ? Cut.belowAll() : AboveValue.belowValue(next); + } + } + throw new AssertionError(); + } + + @Override + Cut withUpperBoundType(BoundType boundType, DiscreteDomain domain) { + switch (boundType) { + case OPEN: { + Comparable next = domain.next(this.endpoint); + return next == null ? Cut.aboveAll() : AboveValue.belowValue(next); + } + case CLOSED: { + return this; + } + } + throw new AssertionError(); + } + + @Override + void describeAsLowerBound(StringBuilder sb) { + sb.append('(').append(this.endpoint); + } + + @Override + void describeAsUpperBound(StringBuilder sb) { + sb.append(this.endpoint).append(']'); + } + + @Override + C leastValueAbove(DiscreteDomain domain) { + return (C)domain.next(this.endpoint); + } + + @Override + C greatestValueBelow(DiscreteDomain domain) { + return (C)this.endpoint; + } + + @Override + Cut canonical(DiscreteDomain domain) { + C next = this.leastValueAbove(domain); + return next != null ? AboveValue.belowValue(next) : Cut.aboveAll(); + } + + public int hashCode() { + return ~this.endpoint.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.endpoint)); + return new StringBuilder(2 + string.length()).append("/").append(string).append("\\").toString(); + } + } + + private static final class BelowValue + extends Cut { + private static final long serialVersionUID = 0L; + + BelowValue(C endpoint) { + super((Comparable)Preconditions.checkNotNull(endpoint)); + } + + @Override + boolean isLessThan(C value) { + return Range.compareOrThrow(this.endpoint, value) <= 0; + } + + @Override + BoundType typeAsLowerBound() { + return BoundType.CLOSED; + } + + @Override + BoundType typeAsUpperBound() { + return BoundType.OPEN; + } + + @Override + Cut withLowerBoundType(BoundType boundType, DiscreteDomain domain) { + switch (boundType) { + case CLOSED: { + return this; + } + case OPEN: { + Comparable previous = domain.previous(this.endpoint); + return previous == null ? Cut.belowAll() : new AboveValue(previous); + } + } + throw new AssertionError(); + } + + @Override + Cut withUpperBoundType(BoundType boundType, DiscreteDomain domain) { + switch (boundType) { + case CLOSED: { + Comparable previous = domain.previous(this.endpoint); + return previous == null ? Cut.aboveAll() : new AboveValue(previous); + } + case OPEN: { + return this; + } + } + throw new AssertionError(); + } + + @Override + void describeAsLowerBound(StringBuilder sb) { + sb.append('[').append(this.endpoint); + } + + @Override + void describeAsUpperBound(StringBuilder sb) { + sb.append(this.endpoint).append(')'); + } + + @Override + C leastValueAbove(DiscreteDomain domain) { + return (C)this.endpoint; + } + + @Override + C greatestValueBelow(DiscreteDomain domain) { + return (C)domain.previous(this.endpoint); + } + + public int hashCode() { + return this.endpoint.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.endpoint)); + return new StringBuilder(2 + string.length()).append("\\").append(string).append("/").toString(); + } + } + + private static final class AboveAll + extends Cut> { + private static final AboveAll INSTANCE = new AboveAll(); + private static final long serialVersionUID = 0L; + + private AboveAll() { + super(null); + } + + @Override + Comparable endpoint() { + throw new IllegalStateException("range unbounded on this side"); + } + + @Override + boolean isLessThan(Comparable value) { + return false; + } + + @Override + BoundType typeAsLowerBound() { + throw new AssertionError((Object)"this statement should be unreachable"); + } + + @Override + BoundType typeAsUpperBound() { + throw new IllegalStateException(); + } + + @Override + Cut> withLowerBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new AssertionError((Object)"this statement should be unreachable"); + } + + @Override + Cut> withUpperBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new IllegalStateException(); + } + + @Override + void describeAsLowerBound(StringBuilder sb) { + throw new AssertionError(); + } + + @Override + void describeAsUpperBound(StringBuilder sb) { + sb.append("+\u221e)"); + } + + @Override + Comparable leastValueAbove(DiscreteDomain> domain) { + throw new AssertionError(); + } + + @Override + Comparable greatestValueBelow(DiscreteDomain> domain) { + return domain.maxValue(); + } + + @Override + public int compareTo(Cut> o) { + return o == this ? 0 : 1; + } + + public String toString() { + return "+\u221e"; + } + + private Object readResolve() { + return INSTANCE; + } + } + + private static final class BelowAll + extends Cut> { + private static final BelowAll INSTANCE = new BelowAll(); + private static final long serialVersionUID = 0L; + + private BelowAll() { + super(null); + } + + @Override + Comparable endpoint() { + throw new IllegalStateException("range unbounded on this side"); + } + + @Override + boolean isLessThan(Comparable value) { + return true; + } + + @Override + BoundType typeAsLowerBound() { + throw new IllegalStateException(); + } + + @Override + BoundType typeAsUpperBound() { + throw new AssertionError((Object)"this statement should be unreachable"); + } + + @Override + Cut> withLowerBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new IllegalStateException(); + } + + @Override + Cut> withUpperBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new AssertionError((Object)"this statement should be unreachable"); + } + + @Override + void describeAsLowerBound(StringBuilder sb) { + sb.append("(-\u221e"); + } + + @Override + void describeAsUpperBound(StringBuilder sb) { + throw new AssertionError(); + } + + @Override + Comparable leastValueAbove(DiscreteDomain> domain) { + return domain.minValue(); + } + + @Override + Comparable greatestValueBelow(DiscreteDomain> domain) { + throw new AssertionError(); + } + + @Override + Cut> canonical(DiscreteDomain> domain) { + try { + return Cut.belowValue(domain.minValue()); + } + catch (NoSuchElementException e) { + return this; + } + } + + @Override + public int compareTo(Cut> o) { + return o == this ? 0 : -1; + } + + public String toString() { + return "-\u221e"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/collect/DenseImmutableTable.java b/src/com/google/common/collect/DenseImmutableTable.java new file mode 100644 index 0000000..6d2d0d2 --- /dev/null +++ b/src/com/google/common/collect/DenseImmutableTable.java @@ -0,0 +1,280 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.RegularImmutableTable; +import com.google.common.collect.Table; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Map; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@GwtCompatible +@Immutable +final class DenseImmutableTable +extends RegularImmutableTable { + private final ImmutableMap rowKeyToIndex; + private final ImmutableMap columnKeyToIndex; + private final ImmutableMap> rowMap; + private final ImmutableMap> columnMap; + private final int[] rowCounts; + private final int[] columnCounts; + private final V[][] values; + private final int[] iterationOrderRow; + private final int[] iterationOrderColumn; + + private static ImmutableMap makeIndex(ImmutableSet set) { + ImmutableMap.Builder indexBuilder = ImmutableMap.builder(); + int i = 0; + for (Object key : set) { + indexBuilder.put(key, i); + ++i; + } + return indexBuilder.build(); + } + + DenseImmutableTable(ImmutableList> cellList, ImmutableSet rowSpace, ImmutableSet columnSpace) { + Object[][] array = new Object[rowSpace.size()][columnSpace.size()]; + this.values = array; + this.rowKeyToIndex = DenseImmutableTable.makeIndex(rowSpace); + this.columnKeyToIndex = DenseImmutableTable.makeIndex(columnSpace); + this.rowCounts = new int[this.rowKeyToIndex.size()]; + this.columnCounts = new int[this.columnKeyToIndex.size()]; + int[] iterationOrderRow = new int[cellList.size()]; + int[] iterationOrderColumn = new int[cellList.size()]; + for (int i = 0; i < cellList.size(); ++i) { + int columnIndex; + Table.Cell cell = (Table.Cell)cellList.get(i); + Object rowKey = cell.getRowKey(); + Object columnKey = cell.getColumnKey(); + int rowIndex = this.rowKeyToIndex.get(rowKey); + V existingValue = this.values[rowIndex][columnIndex = this.columnKeyToIndex.get(columnKey).intValue()]; + Preconditions.checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey); + this.values[rowIndex][columnIndex] = cell.getValue(); + int n = rowIndex; + this.rowCounts[n] = this.rowCounts[n] + 1; + int n2 = columnIndex; + this.columnCounts[n2] = this.columnCounts[n2] + 1; + iterationOrderRow[i] = rowIndex; + iterationOrderColumn[i] = columnIndex; + } + this.iterationOrderRow = iterationOrderRow; + this.iterationOrderColumn = iterationOrderColumn; + this.rowMap = new RowMap(); + this.columnMap = new ColumnMap(); + } + + @Override + public ImmutableMap> columnMap() { + return this.columnMap; + } + + @Override + public ImmutableMap> rowMap() { + return this.rowMap; + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + Integer rowIndex = this.rowKeyToIndex.get(rowKey); + Integer columnIndex = this.columnKeyToIndex.get(columnKey); + return rowIndex == null || columnIndex == null ? null : (V)this.values[rowIndex][columnIndex]; + } + + @Override + public int size() { + return this.iterationOrderRow.length; + } + + @Override + Table.Cell getCell(int index) { + int rowIndex = this.iterationOrderRow[index]; + int columnIndex = this.iterationOrderColumn[index]; + Object rowKey = ((ImmutableCollection)((Object)this.rowKeySet())).asList().get(rowIndex); + Object columnKey = ((ImmutableCollection)((Object)this.columnKeySet())).asList().get(columnIndex); + V value = this.values[rowIndex][columnIndex]; + return DenseImmutableTable.cellOf(rowKey, columnKey, value); + } + + @Override + V getValue(int index) { + return this.values[this.iterationOrderRow[index]][this.iterationOrderColumn[index]]; + } + + private final class ColumnMap + extends ImmutableArrayMap> { + private ColumnMap() { + super(DenseImmutableTable.this.columnCounts.length); + } + + @Override + ImmutableMap keyToIndex() { + return DenseImmutableTable.this.columnKeyToIndex; + } + + @Override + Map getValue(int keyIndex) { + return new Column(keyIndex); + } + + @Override + boolean isPartialView() { + return false; + } + } + + private final class RowMap + extends ImmutableArrayMap> { + private RowMap() { + super(DenseImmutableTable.this.rowCounts.length); + } + + @Override + ImmutableMap keyToIndex() { + return DenseImmutableTable.this.rowKeyToIndex; + } + + @Override + Map getValue(int keyIndex) { + return new Row(keyIndex); + } + + @Override + boolean isPartialView() { + return false; + } + } + + private final class Column + extends ImmutableArrayMap { + private final int columnIndex; + + Column(int columnIndex) { + super(DenseImmutableTable.this.columnCounts[columnIndex]); + this.columnIndex = columnIndex; + } + + @Override + ImmutableMap keyToIndex() { + return DenseImmutableTable.this.rowKeyToIndex; + } + + @Override + V getValue(int keyIndex) { + return DenseImmutableTable.this.values[keyIndex][this.columnIndex]; + } + + @Override + boolean isPartialView() { + return true; + } + } + + private final class Row + extends ImmutableArrayMap { + private final int rowIndex; + + Row(int rowIndex) { + super(DenseImmutableTable.this.rowCounts[rowIndex]); + this.rowIndex = rowIndex; + } + + @Override + ImmutableMap keyToIndex() { + return DenseImmutableTable.this.columnKeyToIndex; + } + + @Override + V getValue(int keyIndex) { + return DenseImmutableTable.this.values[this.rowIndex][keyIndex]; + } + + @Override + boolean isPartialView() { + return true; + } + } + + private static abstract class ImmutableArrayMap + extends ImmutableMap { + private final int size; + + ImmutableArrayMap(int size) { + this.size = size; + } + + abstract ImmutableMap keyToIndex(); + + private boolean isFull() { + return this.size == this.keyToIndex().size(); + } + + K getKey(int index) { + return (K)((ImmutableCollection)((Object)this.keyToIndex().keySet())).asList().get(index); + } + + @Nullable + abstract V getValue(int var1); + + @Override + ImmutableSet createKeySet() { + return this.isFull() ? this.keyToIndex().keySet() : super.createKeySet(); + } + + @Override + public int size() { + return this.size; + } + + @Override + public V get(@Nullable Object key) { + Integer keyIndex = this.keyToIndex().get(key); + return keyIndex == null ? null : (V)this.getValue(keyIndex); + } + + @Override + ImmutableSet> createEntrySet() { + return new ImmutableMapEntrySet(){ + + @Override + ImmutableMap map() { + return ImmutableArrayMap.this; + } + + @Override + public UnmodifiableIterator> iterator() { + return new AbstractIterator>(){ + private int index = -1; + private final int maxIndex; + { + this.maxIndex = ImmutableArrayMap.this.keyToIndex().size(); + } + + @Override + protected Map.Entry computeNext() { + ++this.index; + while (this.index < this.maxIndex) { + Object value = ImmutableArrayMap.this.getValue(this.index); + if (value != null) { + return Maps.immutableEntry(ImmutableArrayMap.this.getKey(this.index), value); + } + ++this.index; + } + return (Map.Entry)this.endOfData(); + } + }; + } + }; + } + } +} diff --git a/src/com/google/common/collect/DescendingImmutableSortedMultiset.java b/src/com/google/common/collect/DescendingImmutableSortedMultiset.java new file mode 100644 index 0000000..15efbc2 --- /dev/null +++ b/src/com/google/common/collect/DescendingImmutableSortedMultiset.java @@ -0,0 +1,70 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.BoundType; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableSortedMultiset; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Multiset; +import javax.annotation.Nullable; + +final class DescendingImmutableSortedMultiset +extends ImmutableSortedMultiset { + private final transient ImmutableSortedMultiset forward; + + DescendingImmutableSortedMultiset(ImmutableSortedMultiset forward) { + this.forward = forward; + } + + @Override + public int count(@Nullable Object element) { + return this.forward.count(element); + } + + @Override + public Multiset.Entry firstEntry() { + return this.forward.lastEntry(); + } + + @Override + public Multiset.Entry lastEntry() { + return this.forward.firstEntry(); + } + + @Override + public int size() { + return this.forward.size(); + } + + @Override + public ImmutableSortedSet elementSet() { + return ((ImmutableSortedSet)this.forward.elementSet()).descendingSet(); + } + + @Override + Multiset.Entry getEntry(int index) { + return (Multiset.Entry)((ImmutableCollection)((Object)this.forward.entrySet())).asList().reverse().get(index); + } + + @Override + public ImmutableSortedMultiset descendingMultiset() { + return this.forward; + } + + @Override + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) { + return ((ImmutableSortedMultiset)this.forward.tailMultiset((Object)upperBound, boundType)).descendingMultiset(); + } + + @Override + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) { + return ((ImmutableSortedMultiset)this.forward.headMultiset((Object)lowerBound, boundType)).descendingMultiset(); + } + + @Override + boolean isPartialView() { + return this.forward.isPartialView(); + } +} diff --git a/src/com/google/common/collect/DescendingImmutableSortedSet.java b/src/com/google/common/collect/DescendingImmutableSortedSet.java new file mode 100644 index 0000000..7ab440c --- /dev/null +++ b/src/com/google/common/collect/DescendingImmutableSortedSet.java @@ -0,0 +1,97 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import com.google.common.collect.UnmodifiableIterator; +import javax.annotation.Nullable; + +class DescendingImmutableSortedSet +extends ImmutableSortedSet { + private final ImmutableSortedSet forward; + + DescendingImmutableSortedSet(ImmutableSortedSet forward) { + super(Ordering.from(forward.comparator()).reverse()); + this.forward = forward; + } + + @Override + public int size() { + return this.forward.size(); + } + + @Override + public UnmodifiableIterator iterator() { + return this.forward.descendingIterator(); + } + + @Override + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) { + return ((ImmutableSortedSet)this.forward.tailSet((Object)toElement, inclusive)).descendingSet(); + } + + @Override + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return ((ImmutableSortedSet)this.forward.subSet((Object)toElement, toInclusive, (Object)fromElement, fromInclusive)).descendingSet(); + } + + @Override + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) { + return ((ImmutableSortedSet)this.forward.headSet((Object)fromElement, inclusive)).descendingSet(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ImmutableSortedSet descendingSet() { + return this.forward; + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return this.forward.iterator(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + ImmutableSortedSet createDescendingSet() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public E lower(E element) { + return this.forward.higher(element); + } + + @Override + public E floor(E element) { + return this.forward.ceiling(element); + } + + @Override + public E ceiling(E element) { + return this.forward.floor(element); + } + + @Override + public E higher(E element) { + return this.forward.lower(element); + } + + @Override + int indexOf(@Nullable Object target) { + int index = this.forward.indexOf(target); + if (index == -1) { + return index; + } + return this.size() - 1 - index; + } + + @Override + boolean isPartialView() { + return this.forward.isPartialView(); + } +} diff --git a/src/com/google/common/collect/DescendingMultiset.java b/src/com/google/common/collect/DescendingMultiset.java new file mode 100644 index 0000000..37d18b0 --- /dev/null +++ b/src/com/google/common/collect/DescendingMultiset.java @@ -0,0 +1,144 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.ForwardingMultiset; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Ordering; +import com.google.common.collect.SortedMultiset; +import com.google.common.collect.SortedMultisets; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; + +@GwtCompatible(emulated=true) +abstract class DescendingMultiset +extends ForwardingMultiset +implements SortedMultiset { + private transient Comparator comparator; + private transient NavigableSet elementSet; + private transient Set> entrySet; + + DescendingMultiset() { + } + + abstract SortedMultiset forwardMultiset(); + + @Override + public Comparator comparator() { + Comparator result = this.comparator; + if (result == null) { + this.comparator = Ordering.from(this.forwardMultiset().comparator()).reverse(); + return this.comparator; + } + return result; + } + + @Override + public NavigableSet elementSet() { + NavigableSet result = this.elementSet; + if (result == null) { + this.elementSet = new SortedMultisets.NavigableElementSet(this); + return this.elementSet; + } + return result; + } + + @Override + public Multiset.Entry pollFirstEntry() { + return this.forwardMultiset().pollLastEntry(); + } + + @Override + public Multiset.Entry pollLastEntry() { + return this.forwardMultiset().pollFirstEntry(); + } + + @Override + public SortedMultiset headMultiset(E toElement, BoundType boundType) { + return this.forwardMultiset().tailMultiset(toElement, boundType).descendingMultiset(); + } + + @Override + public SortedMultiset subMultiset(E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) { + return this.forwardMultiset().subMultiset(toElement, toBoundType, fromElement, fromBoundType).descendingMultiset(); + } + + @Override + public SortedMultiset tailMultiset(E fromElement, BoundType boundType) { + return this.forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset(); + } + + @Override + protected Multiset delegate() { + return this.forwardMultiset(); + } + + @Override + public SortedMultiset descendingMultiset() { + return this.forwardMultiset(); + } + + @Override + public Multiset.Entry firstEntry() { + return this.forwardMultiset().lastEntry(); + } + + @Override + public Multiset.Entry lastEntry() { + return this.forwardMultiset().firstEntry(); + } + + abstract Iterator> entryIterator(); + + @Override + public Set> entrySet() { + Set>> result = this.entrySet; + return result == null ? (this.entrySet = this.createEntrySet()) : result; + } + + Set> createEntrySet() { + return new Multisets.EntrySet(){ + + @Override + Multiset multiset() { + return DescendingMultiset.this; + } + + @Override + public Iterator> iterator() { + return DescendingMultiset.this.entryIterator(); + } + + @Override + public int size() { + return DescendingMultiset.this.forwardMultiset().entrySet().size(); + } + }; + } + + @Override + public Iterator iterator() { + return Multisets.iteratorImpl(this); + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public String toString() { + return this.entrySet().toString(); + } +} diff --git a/src/com/google/common/collect/DiscreteDomain.java b/src/com/google/common/collect/DiscreteDomain.java new file mode 100644 index 0000000..7012145 --- /dev/null +++ b/src/com/google/common/collect/DiscreteDomain.java @@ -0,0 +1,175 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.math.BigInteger; +import java.util.NoSuchElementException; + +@GwtCompatible +@Beta +public abstract class DiscreteDomain { + public static DiscreteDomain integers() { + return IntegerDomain.INSTANCE; + } + + public static DiscreteDomain longs() { + return LongDomain.INSTANCE; + } + + public static DiscreteDomain bigIntegers() { + return BigIntegerDomain.INSTANCE; + } + + protected DiscreteDomain() { + } + + public abstract C next(C var1); + + public abstract C previous(C var1); + + public abstract long distance(C var1, C var2); + + public C minValue() { + throw new NoSuchElementException(); + } + + public C maxValue() { + throw new NoSuchElementException(); + } + + private static final class BigIntegerDomain + extends DiscreteDomain + implements Serializable { + private static final BigIntegerDomain INSTANCE = new BigIntegerDomain(); + private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); + private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); + private static final long serialVersionUID = 0L; + + private BigIntegerDomain() { + } + + @Override + public BigInteger next(BigInteger value) { + return value.add(BigInteger.ONE); + } + + @Override + public BigInteger previous(BigInteger value) { + return value.subtract(BigInteger.ONE); + } + + @Override + public long distance(BigInteger start, BigInteger end) { + return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue(); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "DiscreteDomain.bigIntegers()"; + } + } + + private static final class LongDomain + extends DiscreteDomain + implements Serializable { + private static final LongDomain INSTANCE = new LongDomain(); + private static final long serialVersionUID = 0L; + + private LongDomain() { + } + + @Override + public Long next(Long value) { + long l = value; + return l == Long.MAX_VALUE ? null : Long.valueOf(l + 1L); + } + + @Override + public Long previous(Long value) { + long l = value; + return l == Long.MIN_VALUE ? null : Long.valueOf(l - 1L); + } + + @Override + public long distance(Long start, Long end) { + long result = end - start; + if (end > start && result < 0L) { + return Long.MAX_VALUE; + } + if (end < start && result > 0L) { + return Long.MIN_VALUE; + } + return result; + } + + @Override + public Long minValue() { + return Long.MIN_VALUE; + } + + @Override + public Long maxValue() { + return Long.MAX_VALUE; + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "DiscreteDomain.longs()"; + } + } + + private static final class IntegerDomain + extends DiscreteDomain + implements Serializable { + private static final IntegerDomain INSTANCE = new IntegerDomain(); + private static final long serialVersionUID = 0L; + + private IntegerDomain() { + } + + @Override + public Integer next(Integer value) { + int i = value; + return i == Integer.MAX_VALUE ? null : Integer.valueOf(i + 1); + } + + @Override + public Integer previous(Integer value) { + int i = value; + return i == Integer.MIN_VALUE ? null : Integer.valueOf(i - 1); + } + + @Override + public long distance(Integer start, Integer end) { + return (long)end.intValue() - (long)start.intValue(); + } + + @Override + public Integer minValue() { + return Integer.MIN_VALUE; + } + + @Override + public Integer maxValue() { + return Integer.MAX_VALUE; + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "DiscreteDomain.integers()"; + } + } +} diff --git a/src/com/google/common/collect/EmptyContiguousSet.java b/src/com/google/common/collect/EmptyContiguousSet.java new file mode 100644 index 0000000..66ddc20 --- /dev/null +++ b/src/com/google/common/collect/EmptyContiguousSet.java @@ -0,0 +1,152 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.EmptyImmutableSortedSet; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Ordering; +import com.google.common.collect.Range; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class EmptyContiguousSet +extends ContiguousSet { + EmptyContiguousSet(DiscreteDomain domain) { + super(domain); + } + + @Override + public C first() { + throw new NoSuchElementException(); + } + + @Override + public C last() { + throw new NoSuchElementException(); + } + + @Override + public int size() { + return 0; + } + + @Override + public ContiguousSet intersection(ContiguousSet other) { + return this; + } + + @Override + public Range range() { + throw new NoSuchElementException(); + } + + @Override + public Range range(BoundType lowerBoundType, BoundType upperBoundType) { + throw new NoSuchElementException(); + } + + @Override + ContiguousSet headSetImpl(C toElement, boolean inclusive) { + return this; + } + + @Override + ContiguousSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) { + return this; + } + + @Override + ContiguousSet tailSetImpl(C fromElement, boolean fromInclusive) { + return this; + } + + @Override + @GwtIncompatible(value="not used by GWT emulation") + int indexOf(Object target) { + return -1; + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return Iterators.emptyIterator(); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public ImmutableList asList() { + return ImmutableList.of(); + } + + @Override + public String toString() { + return "[]"; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Set) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new SerializedForm(this.domain); + } + + @Override + @GwtIncompatible(value="NavigableSet") + ImmutableSortedSet createDescendingSet() { + return new EmptyImmutableSortedSet(Ordering.natural().reverse()); + } + + @GwtIncompatible(value="serialization") + private static final class SerializedForm + implements Serializable { + private final DiscreteDomain domain; + private static final long serialVersionUID = 0L; + + private SerializedForm(DiscreteDomain domain) { + this.domain = domain; + } + + private Object readResolve() { + return new EmptyContiguousSet(this.domain); + } + } +} diff --git a/src/com/google/common/collect/EmptyImmutableBiMap.java b/src/com/google/common/collect/EmptyImmutableBiMap.java new file mode 100644 index 0000000..1e763d8 --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableBiMap.java @@ -0,0 +1,69 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class EmptyImmutableBiMap +extends ImmutableBiMap { + static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap(); + + private EmptyImmutableBiMap() { + } + + @Override + public ImmutableBiMap inverse() { + return this; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public Object get(@Nullable Object key) { + return null; + } + + @Override + public ImmutableSet> entrySet() { + return ImmutableSet.of(); + } + + @Override + ImmutableSet> createEntrySet() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableSetMultimap asMultimap() { + return ImmutableSetMultimap.of(); + } + + @Override + public ImmutableSet keySet() { + return ImmutableSet.of(); + } + + @Override + boolean isPartialView() { + return false; + } + + Object readResolve() { + return INSTANCE; + } +} diff --git a/src/com/google/common/collect/EmptyImmutableListMultimap.java b/src/com/google/common/collect/EmptyImmutableListMultimap.java new file mode 100644 index 0000000..8aa7ff0 --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableListMultimap.java @@ -0,0 +1,23 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; + +@GwtCompatible(serializable=true) +class EmptyImmutableListMultimap +extends ImmutableListMultimap { + static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableListMultimap() { + super(ImmutableMap.of(), 0); + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/com/google/common/collect/EmptyImmutableSet.java b/src/com/google/common/collect/EmptyImmutableSet.java new file mode 100644 index 0000000..96693f3 --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableSet.java @@ -0,0 +1,91 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Collection; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class EmptyImmutableSet +extends ImmutableSet { + static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableSet() { + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean contains(@Nullable Object target) { + return false; + } + + @Override + public boolean containsAll(Collection targets) { + return targets.isEmpty(); + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + return offset; + } + + @Override + public ImmutableList asList() { + return ImmutableList.of(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Set) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + @Override + public final int hashCode() { + return 0; + } + + @Override + boolean isHashCodeFast() { + return true; + } + + @Override + public String toString() { + return "[]"; + } + + Object readResolve() { + return INSTANCE; + } +} diff --git a/src/com/google/common/collect/EmptyImmutableSetMultimap.java b/src/com/google/common/collect/EmptyImmutableSetMultimap.java new file mode 100644 index 0000000..bdc9330 --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableSetMultimap.java @@ -0,0 +1,23 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSetMultimap; + +@GwtCompatible(serializable=true) +class EmptyImmutableSetMultimap +extends ImmutableSetMultimap { + static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableSetMultimap() { + super(ImmutableMap.of(), 0, null); + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/com/google/common/collect/EmptyImmutableSortedMap.java b/src/com/google/common/collect/EmptyImmutableSortedMap.java new file mode 100644 index 0000000..5602bf6 --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableSortedMap.java @@ -0,0 +1,99 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import java.util.Comparator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class EmptyImmutableSortedMap +extends ImmutableSortedMap { + private final transient ImmutableSortedSet keySet; + + EmptyImmutableSortedMap(Comparator comparator) { + this.keySet = ImmutableSortedSet.emptySet(comparator); + } + + EmptyImmutableSortedMap(Comparator comparator, ImmutableSortedMap descendingMap) { + super(descendingMap); + this.keySet = ImmutableSortedSet.emptySet(comparator); + } + + @Override + public V get(@Nullable Object key) { + return null; + } + + @Override + public ImmutableSortedSet keySet() { + return this.keySet; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public ImmutableCollection values() { + return ImmutableList.of(); + } + + @Override + public String toString() { + return "{}"; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public ImmutableSet> entrySet() { + return ImmutableSet.of(); + } + + @Override + ImmutableSet> createEntrySet() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableSetMultimap asMultimap() { + return ImmutableSetMultimap.of(); + } + + @Override + public ImmutableSortedMap headMap(K toKey, boolean inclusive) { + Preconditions.checkNotNull(toKey); + return this; + } + + @Override + public ImmutableSortedMap tailMap(K fromKey, boolean inclusive) { + Preconditions.checkNotNull(fromKey); + return this; + } + + @Override + ImmutableSortedMap createDescendingMap() { + return new EmptyImmutableSortedMap(Ordering.from(this.comparator()).reverse(), this); + } +} diff --git a/src/com/google/common/collect/EmptyImmutableSortedMultiset.java b/src/com/google/common/collect/EmptyImmutableSortedMultiset.java new file mode 100644 index 0000000..24ebebf --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableSortedMultiset.java @@ -0,0 +1,103 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMultiset; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multiset; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Collection; +import java.util.Comparator; +import javax.annotation.Nullable; + +final class EmptyImmutableSortedMultiset +extends ImmutableSortedMultiset { + private final ImmutableSortedSet elementSet; + + EmptyImmutableSortedMultiset(Comparator comparator) { + this.elementSet = ImmutableSortedSet.emptySet(comparator); + } + + @Override + public Multiset.Entry firstEntry() { + return null; + } + + @Override + public Multiset.Entry lastEntry() { + return null; + } + + @Override + public int count(@Nullable Object element) { + return 0; + } + + @Override + public boolean containsAll(Collection targets) { + return targets.isEmpty(); + } + + @Override + public int size() { + return 0; + } + + @Override + public ImmutableSortedSet elementSet() { + return this.elementSet; + } + + @Override + Multiset.Entry getEntry(int index) { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) { + Preconditions.checkNotNull(upperBound); + Preconditions.checkNotNull(boundType); + return this; + } + + @Override + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) { + Preconditions.checkNotNull(lowerBound); + Preconditions.checkNotNull(boundType); + return this; + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Multiset) { + Multiset other = (Multiset)object; + return other.isEmpty(); + } + return false; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + return offset; + } + + @Override + public ImmutableList asList() { + return ImmutableList.of(); + } +} diff --git a/src/com/google/common/collect/EmptyImmutableSortedSet.java b/src/com/google/common/collect/EmptyImmutableSortedSet.java new file mode 100644 index 0000000..6224aea --- /dev/null +++ b/src/com/google/common/collect/EmptyImmutableSortedSet.java @@ -0,0 +1,125 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Ordering; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Collection; +import java.util.Comparator; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +class EmptyImmutableSortedSet +extends ImmutableSortedSet { + EmptyImmutableSortedSet(Comparator comparator) { + super(comparator); + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean contains(@Nullable Object target) { + return false; + } + + @Override + public boolean containsAll(Collection targets) { + return targets.isEmpty(); + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return Iterators.emptyIterator(); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public ImmutableList asList() { + return ImmutableList.of(); + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + return offset; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Set) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return "[]"; + } + + @Override + public E first() { + throw new NoSuchElementException(); + } + + @Override + public E last() { + throw new NoSuchElementException(); + } + + @Override + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) { + return this; + } + + @Override + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return this; + } + + @Override + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) { + return this; + } + + @Override + int indexOf(@Nullable Object target) { + return -1; + } + + @Override + ImmutableSortedSet createDescendingSet() { + return new EmptyImmutableSortedSet(Ordering.from(this.comparator).reverse()); + } +} diff --git a/src/com/google/common/collect/EnumBiMap.java b/src/com/google/common/collect/EnumBiMap.java new file mode 100644 index 0000000..df4e412 --- /dev/null +++ b/src/com/google/common/collect/EnumBiMap.java @@ -0,0 +1,96 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractBiMap; +import com.google.common.collect.EnumHashBiMap; +import com.google.common.collect.Serialization; +import com.google.common.collect.WellBehavedMap; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumMap; +import java.util.Map; + +@GwtCompatible(emulated=true) +public final class EnumBiMap, V extends Enum> +extends AbstractBiMap { + private transient Class keyType; + private transient Class valueType; + @GwtIncompatible(value="not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static , V extends Enum> EnumBiMap create(Class keyType, Class valueType) { + return new EnumBiMap(keyType, valueType); + } + + public static , V extends Enum> EnumBiMap create(Map map) { + EnumBiMap bimap = EnumBiMap.create(EnumBiMap.inferKeyType(map), EnumBiMap.inferValueType(map)); + bimap.putAll((Map)map); + return bimap; + } + + private EnumBiMap(Class keyType, Class valueType) { + super(WellBehavedMap.wrap(new EnumMap(keyType)), WellBehavedMap.wrap(new EnumMap(valueType))); + this.keyType = keyType; + this.valueType = valueType; + } + + static > Class inferKeyType(Map map) { + if (map instanceof EnumBiMap) { + return ((EnumBiMap)map).keyType(); + } + if (map instanceof EnumHashBiMap) { + return ((EnumHashBiMap)map).keyType(); + } + Preconditions.checkArgument(!map.isEmpty()); + return ((Enum)map.keySet().iterator().next()).getDeclaringClass(); + } + + private static > Class inferValueType(Map map) { + if (map instanceof EnumBiMap) { + return ((EnumBiMap)map).valueType; + } + Preconditions.checkArgument(!map.isEmpty()); + return ((Enum)map.values().iterator().next()).getDeclaringClass(); + } + + public Class keyType() { + return this.keyType; + } + + public Class valueType() { + return this.valueType; + } + + @Override + K checkKey(K key) { + return (K)((Enum)Preconditions.checkNotNull(key)); + } + + @Override + V checkValue(V value) { + return (V)((Enum)Preconditions.checkNotNull(value)); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.keyType); + stream.writeObject(this.valueType); + Serialization.writeMap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.keyType = (Class)stream.readObject(); + this.valueType = (Class)stream.readObject(); + this.setDelegates(WellBehavedMap.wrap(new EnumMap(this.keyType)), WellBehavedMap.wrap(new EnumMap(this.valueType))); + Serialization.populateMap(this, stream); + } +} diff --git a/src/com/google/common/collect/EnumHashBiMap.java b/src/com/google/common/collect/EnumHashBiMap.java new file mode 100644 index 0000000..d615573 --- /dev/null +++ b/src/com/google/common/collect/EnumHashBiMap.java @@ -0,0 +1,77 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractBiMap; +import com.google.common.collect.EnumBiMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Serialization; +import com.google.common.collect.WellBehavedMap; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class EnumHashBiMap, V> +extends AbstractBiMap { + private transient Class keyType; + @GwtIncompatible(value="only needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static , V> EnumHashBiMap create(Class keyType) { + return new EnumHashBiMap(keyType); + } + + public static , V> EnumHashBiMap create(Map map) { + EnumHashBiMap bimap = EnumHashBiMap.create(EnumBiMap.inferKeyType(map)); + bimap.putAll((Map)map); + return bimap; + } + + private EnumHashBiMap(Class keyType) { + super(WellBehavedMap.wrap(new EnumMap(keyType)), Maps.newHashMapWithExpectedSize(((Enum[])keyType.getEnumConstants()).length)); + this.keyType = keyType; + } + + @Override + K checkKey(K key) { + return (K)((Enum)Preconditions.checkNotNull(key)); + } + + @Override + public V put(K key, @Nullable V value) { + return super.put(key, value); + } + + @Override + public V forcePut(K key, @Nullable V value) { + return super.forcePut(key, value); + } + + public Class keyType() { + return this.keyType; + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.keyType); + Serialization.writeMap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.keyType = (Class)stream.readObject(); + this.setDelegates(WellBehavedMap.wrap(new EnumMap(this.keyType)), new HashMap(((Enum[])this.keyType.getEnumConstants()).length * 3 / 2)); + Serialization.populateMap(this, stream); + } +} diff --git a/src/com/google/common/collect/EnumMultiset.java b/src/com/google/common/collect/EnumMultiset.java new file mode 100644 index 0000000..d9540af --- /dev/null +++ b/src/com/google/common/collect/EnumMultiset.java @@ -0,0 +1,64 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapBasedMultiset; +import com.google.common.collect.Iterables; +import com.google.common.collect.Serialization; +import com.google.common.collect.WellBehavedMap; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumMap; +import java.util.Iterator; + +@GwtCompatible(emulated=true) +public final class EnumMultiset> +extends AbstractMapBasedMultiset { + private transient Class type; + @GwtIncompatible(value="Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static > EnumMultiset create(Class type) { + return new EnumMultiset(type); + } + + public static > EnumMultiset create(Iterable elements) { + Iterator iterator = elements.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable"); + EnumMultiset multiset = new EnumMultiset(((Enum)iterator.next()).getDeclaringClass()); + Iterables.addAll(multiset, elements); + return multiset; + } + + public static > EnumMultiset create(Iterable elements, Class type) { + EnumMultiset result = EnumMultiset.create(type); + Iterables.addAll(result, elements); + return result; + } + + private EnumMultiset(Class type) { + super(WellBehavedMap.wrap(new EnumMap(type))); + this.type = type; + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.type); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + Class localType; + stream.defaultReadObject(); + this.type = localType = (Class)stream.readObject(); + this.setBackingMap(WellBehavedMap.wrap(new EnumMap(this.type))); + Serialization.populateMultiset(this, stream); + } +} diff --git a/src/com/google/common/collect/EvictingQueue.java b/src/com/google/common/collect/EvictingQueue.java new file mode 100644 index 0000000..f6966bb --- /dev/null +++ b/src/com/google/common/collect/EvictingQueue.java @@ -0,0 +1,77 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingQueue; +import java.io.Serializable; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Queue; + +@Beta +@GwtIncompatible(value="java.util.ArrayDeque") +public final class EvictingQueue +extends ForwardingQueue +implements Serializable { + private final Queue delegate; + @VisibleForTesting + final int maxSize; + private static final long serialVersionUID = 0L; + + private EvictingQueue(int maxSize) { + Preconditions.checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", maxSize); + this.delegate = new ArrayDeque(maxSize); + this.maxSize = maxSize; + } + + public static EvictingQueue create(int maxSize) { + return new EvictingQueue(maxSize); + } + + public int remainingCapacity() { + return this.maxSize - this.size(); + } + + @Override + protected Queue delegate() { + return this.delegate; + } + + @Override + public boolean offer(E e) { + return this.add(e); + } + + @Override + public boolean add(E e) { + Preconditions.checkNotNull(e); + if (this.maxSize == 0) { + return true; + } + if (this.size() == this.maxSize) { + this.delegate.remove(); + } + this.delegate.add(e); + return true; + } + + @Override + public boolean addAll(Collection collection) { + return this.standardAddAll(collection); + } + + @Override + public boolean contains(Object object) { + return this.delegate().contains(Preconditions.checkNotNull(object)); + } + + @Override + public boolean remove(Object object) { + return this.delegate().remove(Preconditions.checkNotNull(object)); + } +} diff --git a/src/com/google/common/collect/ExplicitOrdering.java b/src/com/google/common/collect/ExplicitOrdering.java new file mode 100644 index 0000000..311abdd --- /dev/null +++ b/src/com/google/common/collect/ExplicitOrdering.java @@ -0,0 +1,67 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class ExplicitOrdering +extends Ordering +implements Serializable { + final ImmutableMap rankMap; + private static final long serialVersionUID = 0L; + + ExplicitOrdering(List valuesInOrder) { + this(ExplicitOrdering.buildRankMap(valuesInOrder)); + } + + ExplicitOrdering(ImmutableMap rankMap) { + this.rankMap = rankMap; + } + + @Override + public int compare(T left, T right) { + return this.rank(left) - this.rank(right); + } + + private int rank(T value) { + Integer rank = this.rankMap.get(value); + if (rank == null) { + throw new Ordering.IncomparableValueException(value); + } + return rank; + } + + private static ImmutableMap buildRankMap(List valuesInOrder) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + int rank = 0; + for (T value : valuesInOrder) { + builder.put(value, rank++); + } + return builder.build(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof ExplicitOrdering) { + ExplicitOrdering that = (ExplicitOrdering)object; + return this.rankMap.equals(that.rankMap); + } + return false; + } + + public int hashCode() { + return this.rankMap.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.rankMap.keySet())); + return new StringBuilder(19 + string.length()).append("Ordering.explicit(").append(string).append(")").toString(); + } +} diff --git a/src/com/google/common/collect/FilteredEntryMultimap.java b/src/com/google/common/collect/FilteredEntryMultimap.java new file mode 100644 index 0000000..0aab9b9 --- /dev/null +++ b/src/com/google/common/collect/FilteredEntryMultimap.java @@ -0,0 +1,382 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.FilteredMultimap; +import com.google.common.collect.FilteredMultimapValues; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +class FilteredEntryMultimap +extends AbstractMultimap +implements FilteredMultimap { + final Multimap unfiltered; + final Predicate> predicate; + + FilteredEntryMultimap(Multimap unfiltered, Predicate> predicate) { + this.unfiltered = Preconditions.checkNotNull(unfiltered); + this.predicate = Preconditions.checkNotNull(predicate); + } + + @Override + public Multimap unfiltered() { + return this.unfiltered; + } + + @Override + public Predicate> entryPredicate() { + return this.predicate; + } + + @Override + public int size() { + return this.entries().size(); + } + + private boolean satisfies(K key, V value) { + return this.predicate.apply(Maps.immutableEntry(key, value)); + } + + static Collection filterCollection(Collection collection, Predicate predicate) { + if (collection instanceof Set) { + return Sets.filter((Set)collection, predicate); + } + return Collections2.filter(collection, predicate); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.asMap().get(key) != null; + } + + @Override + public Collection removeAll(@Nullable Object key) { + return MoreObjects.firstNonNull(this.asMap().remove(key), this.unmodifiableEmptyCollection()); + } + + Collection unmodifiableEmptyCollection() { + return this.unfiltered instanceof SetMultimap ? Collections.emptySet() : Collections.emptyList(); + } + + @Override + public void clear() { + this.entries().clear(); + } + + @Override + public Collection get(K key) { + return FilteredEntryMultimap.filterCollection(this.unfiltered.get(key), new ValuePredicate(key)); + } + + @Override + Collection> createEntries() { + return FilteredEntryMultimap.filterCollection(this.unfiltered.entries(), this.predicate); + } + + @Override + Collection createValues() { + return new FilteredMultimapValues(this); + } + + @Override + Iterator> entryIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + Map> createAsMap() { + return new AsMap(); + } + + @Override + public Set keySet() { + return this.asMap().keySet(); + } + + boolean removeEntriesIf(Predicate>> predicate) { + Iterator>> entryIterator = this.unfiltered.asMap().entrySet().iterator(); + boolean changed = false; + while (entryIterator.hasNext()) { + Map.Entry> entry = entryIterator.next(); + K key = entry.getKey(); + Collection collection = FilteredEntryMultimap.filterCollection(entry.getValue(), new ValuePredicate(key)); + if (collection.isEmpty() || !predicate.apply(Maps.immutableEntry(key, collection))) continue; + if (collection.size() == entry.getValue().size()) { + entryIterator.remove(); + } else { + collection.clear(); + } + changed = true; + } + return changed; + } + + @Override + Multiset createKeys() { + return new Keys(); + } + + class Keys + extends Multimaps.Keys { + Keys() { + super(FilteredEntryMultimap.this); + } + + @Override + public int remove(@Nullable Object key, int occurrences) { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return this.count(key); + } + Collection collection = FilteredEntryMultimap.this.unfiltered.asMap().get(key); + if (collection == null) { + return 0; + } + Object k = key; + int oldCount = 0; + Iterator itr = collection.iterator(); + while (itr.hasNext()) { + Object v = itr.next(); + if (!FilteredEntryMultimap.this.satisfies(k, v) || ++oldCount > occurrences) continue; + itr.remove(); + } + return oldCount; + } + + @Override + public Set> entrySet() { + return new Multisets.EntrySet(){ + + @Override + Multiset multiset() { + return Keys.this; + } + + @Override + public Iterator> iterator() { + return Keys.this.entryIterator(); + } + + @Override + public int size() { + return FilteredEntryMultimap.this.keySet().size(); + } + + private boolean removeEntriesIf(final Predicate> predicate) { + return FilteredEntryMultimap.this.removeEntriesIf(new Predicate>>(){ + + @Override + public boolean apply(Map.Entry> entry) { + return predicate.apply(Multisets.immutableEntry(entry.getKey(), entry.getValue().size())); + } + }); + } + + @Override + public boolean removeAll(Collection c) { + return this.removeEntriesIf(Predicates.in(c)); + } + + @Override + public boolean retainAll(Collection c) { + return this.removeEntriesIf(Predicates.not(Predicates.in(c))); + } + }; + } + } + + class AsMap + extends Maps.ImprovedAbstractMap> { + AsMap() { + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.get(key) != null; + } + + @Override + public void clear() { + FilteredEntryMultimap.this.clear(); + } + + @Override + public Collection get(@Nullable Object key) { + Collection result = FilteredEntryMultimap.this.unfiltered.asMap().get(key); + if (result == null) { + return null; + } + Object k = key; + return (result = FilteredEntryMultimap.filterCollection(result, new ValuePredicate(k))).isEmpty() ? null : result; + } + + @Override + public Collection remove(@Nullable Object key) { + Collection collection = FilteredEntryMultimap.this.unfiltered.asMap().get(key); + if (collection == null) { + return null; + } + Object k = key; + ArrayList result = Lists.newArrayList(); + Iterator itr = collection.iterator(); + while (itr.hasNext()) { + Object v = itr.next(); + if (!FilteredEntryMultimap.this.satisfies(k, v)) continue; + itr.remove(); + result.add(v); + } + if (result.isEmpty()) { + return null; + } + if (FilteredEntryMultimap.this.unfiltered instanceof SetMultimap) { + return Collections.unmodifiableSet(Sets.newLinkedHashSet(result)); + } + return Collections.unmodifiableList(result); + } + + @Override + Set createKeySet() { + return new Maps.KeySet>(this){ + + @Override + public boolean removeAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Maps.keyPredicateOnEntries(Predicates.in(c))); + } + + @Override + public boolean retainAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + + @Override + public boolean remove(@Nullable Object o) { + return AsMap.this.remove(o) != null; + } + }; + } + + @Override + Set>> createEntrySet() { + return new Maps.EntrySet>(){ + + @Override + Map> map() { + return AsMap.this; + } + + @Override + public Iterator>> iterator() { + return new AbstractIterator>>(){ + final Iterator>> backingIterator; + { + this.backingIterator = FilteredEntryMultimap.this.unfiltered.asMap().entrySet().iterator(); + } + + @Override + protected Map.Entry> computeNext() { + while (this.backingIterator.hasNext()) { + Map.Entry entry = this.backingIterator.next(); + Object key = entry.getKey(); + Collection collection = FilteredEntryMultimap.filterCollection(entry.getValue(), new ValuePredicate(key)); + if (collection.isEmpty()) continue; + return Maps.immutableEntry(key, collection); + } + return (Map.Entry)this.endOfData(); + } + }; + } + + @Override + public boolean removeAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Predicates.in(c)); + } + + @Override + public boolean retainAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Predicates.not(Predicates.in(c))); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + }; + } + + @Override + Collection> createValues() { + return new Maps.Values>(this){ + + @Override + public boolean remove(@Nullable Object o) { + if (o instanceof Collection) { + Collection c = (Collection)o; + Iterator entryIterator = FilteredEntryMultimap.this.unfiltered.asMap().entrySet().iterator(); + while (entryIterator.hasNext()) { + Map.Entry entry = entryIterator.next(); + Object key = entry.getKey(); + Collection collection = FilteredEntryMultimap.filterCollection(entry.getValue(), new ValuePredicate(key)); + if (collection.isEmpty() || !c.equals(collection)) continue; + if (collection.size() == entry.getValue().size()) { + entryIterator.remove(); + } else { + collection.clear(); + } + return true; + } + } + return false; + } + + @Override + public boolean removeAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Maps.valuePredicateOnEntries(Predicates.in(c))); + } + + @Override + public boolean retainAll(Collection c) { + return FilteredEntryMultimap.this.removeEntriesIf(Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + }; + } + } + + final class ValuePredicate + implements Predicate { + private final K key; + + ValuePredicate(K key) { + this.key = key; + } + + @Override + public boolean apply(@Nullable V value) { + return FilteredEntryMultimap.this.satisfies(this.key, value); + } + } +} diff --git a/src/com/google/common/collect/FilteredEntrySetMultimap.java b/src/com/google/common/collect/FilteredEntrySetMultimap.java new file mode 100644 index 0000000..e6ce04f --- /dev/null +++ b/src/com/google/common/collect/FilteredEntrySetMultimap.java @@ -0,0 +1,52 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import com.google.common.collect.FilteredEntryMultimap; +import com.google.common.collect.FilteredSetMultimap; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.util.Map; +import java.util.Set; + +@GwtCompatible +final class FilteredEntrySetMultimap +extends FilteredEntryMultimap +implements FilteredSetMultimap { + FilteredEntrySetMultimap(SetMultimap unfiltered, Predicate> predicate) { + super(unfiltered, predicate); + } + + @Override + public SetMultimap unfiltered() { + return (SetMultimap)this.unfiltered; + } + + @Override + public Set get(K key) { + return (Set)super.get(key); + } + + @Override + public Set removeAll(Object key) { + return (Set)super.removeAll(key); + } + + @Override + public Set replaceValues(K key, Iterable values) { + return (Set)super.replaceValues(key, values); + } + + @Override + Set> createEntries() { + return Sets.filter(this.unfiltered().entries(), this.entryPredicate()); + } + + @Override + public Set> entries() { + return (Set)super.entries(); + } +} diff --git a/src/com/google/common/collect/FilteredKeyListMultimap.java b/src/com/google/common/collect/FilteredKeyListMultimap.java new file mode 100644 index 0000000..87438a1 --- /dev/null +++ b/src/com/google/common/collect/FilteredKeyListMultimap.java @@ -0,0 +1,40 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import com.google.common.collect.FilteredKeyMultimap; +import com.google.common.collect.ListMultimap; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible +final class FilteredKeyListMultimap +extends FilteredKeyMultimap +implements ListMultimap { + FilteredKeyListMultimap(ListMultimap unfiltered, Predicate keyPredicate) { + super(unfiltered, keyPredicate); + } + + @Override + public ListMultimap unfiltered() { + return (ListMultimap)super.unfiltered(); + } + + @Override + public List get(K key) { + return (List)super.get(key); + } + + @Override + public List removeAll(@Nullable Object key) { + return (List)super.removeAll(key); + } + + @Override + public List replaceValues(K key, Iterable values) { + return (List)super.replaceValues(key, values); + } +} diff --git a/src/com/google/common/collect/FilteredKeyMultimap.java b/src/com/google/common/collect/FilteredKeyMultimap.java new file mode 100644 index 0000000..ed4fab7 --- /dev/null +++ b/src/com/google/common/collect/FilteredKeyMultimap.java @@ -0,0 +1,217 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.Collections2; +import com.google.common.collect.FilteredMultimap; +import com.google.common.collect.FilteredMultimapValues; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingList; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +class FilteredKeyMultimap +extends AbstractMultimap +implements FilteredMultimap { + final Multimap unfiltered; + final Predicate keyPredicate; + + FilteredKeyMultimap(Multimap unfiltered, Predicate keyPredicate) { + this.unfiltered = Preconditions.checkNotNull(unfiltered); + this.keyPredicate = Preconditions.checkNotNull(keyPredicate); + } + + @Override + public Multimap unfiltered() { + return this.unfiltered; + } + + @Override + public Predicate> entryPredicate() { + return Maps.keyPredicateOnEntries(this.keyPredicate); + } + + @Override + public int size() { + int size = 0; + for (Collection collection : this.asMap().values()) { + size += collection.size(); + } + return size; + } + + @Override + public boolean containsKey(@Nullable Object key) { + if (this.unfiltered.containsKey(key)) { + Object k = key; + return this.keyPredicate.apply(k); + } + return false; + } + + @Override + public Collection removeAll(Object key) { + return this.containsKey(key) ? this.unfiltered.removeAll(key) : this.unmodifiableEmptyCollection(); + } + + Collection unmodifiableEmptyCollection() { + if (this.unfiltered instanceof SetMultimap) { + return ImmutableSet.of(); + } + return ImmutableList.of(); + } + + @Override + public void clear() { + this.keySet().clear(); + } + + @Override + Set createKeySet() { + return Sets.filter(this.unfiltered.keySet(), this.keyPredicate); + } + + @Override + public Collection get(K key) { + if (this.keyPredicate.apply(key)) { + return this.unfiltered.get(key); + } + if (this.unfiltered instanceof SetMultimap) { + return new AddRejectingSet(key); + } + return new AddRejectingList(key); + } + + @Override + Iterator> entryIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + Collection> createEntries() { + return new Entries(); + } + + @Override + Collection createValues() { + return new FilteredMultimapValues(this); + } + + @Override + Map> createAsMap() { + return Maps.filterKeys(this.unfiltered.asMap(), this.keyPredicate); + } + + @Override + Multiset createKeys() { + return Multisets.filter(this.unfiltered.keys(), this.keyPredicate); + } + + class Entries + extends ForwardingCollection> { + Entries() { + } + + @Override + protected Collection> delegate() { + return Collections2.filter(FilteredKeyMultimap.this.unfiltered.entries(), FilteredKeyMultimap.this.entryPredicate()); + } + + @Override + public boolean remove(@Nullable Object o) { + Map.Entry entry; + if (o instanceof Map.Entry && FilteredKeyMultimap.this.unfiltered.containsKey((entry = (Map.Entry)o).getKey()) && FilteredKeyMultimap.this.keyPredicate.apply(entry.getKey())) { + return FilteredKeyMultimap.this.unfiltered.remove(entry.getKey(), entry.getValue()); + } + return false; + } + } + + static class AddRejectingList + extends ForwardingList { + final K key; + + AddRejectingList(K key) { + this.key = key; + } + + @Override + public boolean add(V v) { + this.add(0, v); + return true; + } + + @Override + public boolean addAll(Collection collection) { + this.addAll(0, collection); + return true; + } + + @Override + public void add(int index, V element) { + Preconditions.checkPositionIndex(index, 0); + String string = String.valueOf(String.valueOf(this.key)); + throw new IllegalArgumentException(new StringBuilder(32 + string.length()).append("Key does not satisfy predicate: ").append(string).toString()); + } + + @Override + public boolean addAll(int index, Collection elements) { + Preconditions.checkNotNull(elements); + Preconditions.checkPositionIndex(index, 0); + String string = String.valueOf(String.valueOf(this.key)); + throw new IllegalArgumentException(new StringBuilder(32 + string.length()).append("Key does not satisfy predicate: ").append(string).toString()); + } + + @Override + protected List delegate() { + return Collections.emptyList(); + } + } + + static class AddRejectingSet + extends ForwardingSet { + final K key; + + AddRejectingSet(K key) { + this.key = key; + } + + @Override + public boolean add(V element) { + String string = String.valueOf(String.valueOf(this.key)); + throw new IllegalArgumentException(new StringBuilder(32 + string.length()).append("Key does not satisfy predicate: ").append(string).toString()); + } + + @Override + public boolean addAll(Collection collection) { + Preconditions.checkNotNull(collection); + String string = String.valueOf(String.valueOf(this.key)); + throw new IllegalArgumentException(new StringBuilder(32 + string.length()).append("Key does not satisfy predicate: ").append(string).toString()); + } + + @Override + protected Set delegate() { + return Collections.emptySet(); + } + } +} diff --git a/src/com/google/common/collect/FilteredKeySetMultimap.java b/src/com/google/common/collect/FilteredKeySetMultimap.java new file mode 100644 index 0000000..9bf23e5 --- /dev/null +++ b/src/com/google/common/collect/FilteredKeySetMultimap.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import com.google.common.collect.FilteredKeyMultimap; +import com.google.common.collect.FilteredSetMultimap; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +final class FilteredKeySetMultimap +extends FilteredKeyMultimap +implements FilteredSetMultimap { + FilteredKeySetMultimap(SetMultimap unfiltered, Predicate keyPredicate) { + super(unfiltered, keyPredicate); + } + + @Override + public SetMultimap unfiltered() { + return (SetMultimap)this.unfiltered; + } + + @Override + public Set get(K key) { + return (Set)super.get(key); + } + + @Override + public Set removeAll(Object key) { + return (Set)super.removeAll(key); + } + + @Override + public Set replaceValues(K key, Iterable values) { + return (Set)super.replaceValues(key, values); + } + + @Override + public Set> entries() { + return (Set)super.entries(); + } + + @Override + Set> createEntries() { + return new EntrySet(); + } + + class EntrySet + extends FilteredKeyMultimap.Entries + implements Set> { + EntrySet() { + super(FilteredKeySetMultimap.this); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + @Override + public boolean equals(@Nullable Object o) { + return Sets.equalsImpl(this, o); + } + } +} diff --git a/src/com/google/common/collect/FilteredMultimap.java b/src/com/google/common/collect/FilteredMultimap.java new file mode 100644 index 0000000..066db97 --- /dev/null +++ b/src/com/google/common/collect/FilteredMultimap.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import com.google.common.collect.Multimap; +import java.util.Map; + +@GwtCompatible +interface FilteredMultimap +extends Multimap { + public Multimap unfiltered(); + + public Predicate> entryPredicate(); +} diff --git a/src/com/google/common/collect/FilteredMultimapValues.java b/src/com/google/common/collect/FilteredMultimapValues.java new file mode 100644 index 0000000..eb18545 --- /dev/null +++ b/src/com/google/common/collect/FilteredMultimapValues.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.FilteredMultimap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +final class FilteredMultimapValues +extends AbstractCollection { + private final FilteredMultimap multimap; + + FilteredMultimapValues(FilteredMultimap multimap) { + this.multimap = Preconditions.checkNotNull(multimap); + } + + @Override + public Iterator iterator() { + return Maps.valueIterator(this.multimap.entries().iterator()); + } + + @Override + public boolean contains(@Nullable Object o) { + return this.multimap.containsValue(o); + } + + @Override + public int size() { + return this.multimap.size(); + } + + @Override + public boolean remove(@Nullable Object o) { + Predicate> entryPredicate = this.multimap.entryPredicate(); + Iterator> unfilteredItr = this.multimap.unfiltered().entries().iterator(); + while (unfilteredItr.hasNext()) { + Map.Entry entry = unfilteredItr.next(); + if (!entryPredicate.apply(entry) || !Objects.equal(entry.getValue(), o)) continue; + unfilteredItr.remove(); + return true; + } + return false; + } + + @Override + public boolean removeAll(Collection c) { + return Iterables.removeIf(this.multimap.unfiltered().entries(), Predicates.and(this.multimap.entryPredicate(), Maps.valuePredicateOnEntries(Predicates.in(c)))); + } + + @Override + public boolean retainAll(Collection c) { + return Iterables.removeIf(this.multimap.unfiltered().entries(), Predicates.and(this.multimap.entryPredicate(), Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c))))); + } + + @Override + public void clear() { + this.multimap.clear(); + } +} diff --git a/src/com/google/common/collect/FilteredSetMultimap.java b/src/com/google/common/collect/FilteredSetMultimap.java new file mode 100644 index 0000000..216671d --- /dev/null +++ b/src/com/google/common/collect/FilteredSetMultimap.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.FilteredMultimap; +import com.google.common.collect.SetMultimap; + +@GwtCompatible +interface FilteredSetMultimap +extends FilteredMultimap, +SetMultimap { + @Override + public SetMultimap unfiltered(); +} diff --git a/src/com/google/common/collect/FluentIterable.java b/src/com/google/common/collect/FluentIterable.java new file mode 100644 index 0000000..ffbffaf --- /dev/null +++ b/src/com/google/common/collect/FluentIterable.java @@ -0,0 +1,233 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Ordering; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.SortedSet; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public abstract class FluentIterable +implements Iterable { + private final Iterable iterable; + + protected FluentIterable() { + this.iterable = this; + } + + FluentIterable(Iterable iterable) { + this.iterable = Preconditions.checkNotNull(iterable); + } + + public static FluentIterable from(final Iterable iterable) { + return iterable instanceof FluentIterable ? (FluentIterable)iterable : new FluentIterable(iterable){ + + @Override + public Iterator iterator() { + return iterable.iterator(); + } + }; + } + + @Deprecated + public static FluentIterable from(FluentIterable iterable) { + return Preconditions.checkNotNull(iterable); + } + + @Beta + public static FluentIterable of(E[] elements) { + return FluentIterable.from(Lists.newArrayList(elements)); + } + + public String toString() { + return Iterables.toString(this.iterable); + } + + public final int size() { + return Iterables.size(this.iterable); + } + + public final boolean contains(@Nullable Object element) { + return Iterables.contains(this.iterable, element); + } + + @CheckReturnValue + public final FluentIterable cycle() { + return FluentIterable.from(Iterables.cycle(this.iterable)); + } + + @CheckReturnValue + @Beta + public final FluentIterable append(Iterable other) { + return FluentIterable.from(Iterables.concat(this.iterable, other)); + } + + @CheckReturnValue + @Beta + public final FluentIterable append(E ... elements) { + return FluentIterable.from(Iterables.concat(this.iterable, Arrays.asList(elements))); + } + + @CheckReturnValue + public final FluentIterable filter(Predicate predicate) { + return FluentIterable.from(Iterables.filter(this.iterable, predicate)); + } + + @CheckReturnValue + @GwtIncompatible(value="Class.isInstance") + public final FluentIterable filter(Class type) { + return FluentIterable.from(Iterables.filter(this.iterable, type)); + } + + public final boolean anyMatch(Predicate predicate) { + return Iterables.any(this.iterable, predicate); + } + + public final boolean allMatch(Predicate predicate) { + return Iterables.all(this.iterable, predicate); + } + + public final Optional firstMatch(Predicate predicate) { + return Iterables.tryFind(this.iterable, predicate); + } + + public final FluentIterable transform(Function function) { + return FluentIterable.from(Iterables.transform(this.iterable, function)); + } + + public FluentIterable transformAndConcat(Function> function) { + return FluentIterable.from(Iterables.concat(this.transform(function))); + } + + public final Optional first() { + Iterator iterator = this.iterable.iterator(); + return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.absent(); + } + + public final Optional last() { + E current; + if (this.iterable instanceof List) { + List list = (List)this.iterable; + if (list.isEmpty()) { + return Optional.absent(); + } + return Optional.of(list.get(list.size() - 1)); + } + Iterator iterator = this.iterable.iterator(); + if (!iterator.hasNext()) { + return Optional.absent(); + } + if (this.iterable instanceof SortedSet) { + SortedSet sortedSet = (SortedSet)this.iterable; + return Optional.of(sortedSet.last()); + } + do { + current = iterator.next(); + } while (iterator.hasNext()); + return Optional.of(current); + } + + @CheckReturnValue + public final FluentIterable skip(int numberToSkip) { + return FluentIterable.from(Iterables.skip(this.iterable, numberToSkip)); + } + + @CheckReturnValue + public final FluentIterable limit(int size) { + return FluentIterable.from(Iterables.limit(this.iterable, size)); + } + + public final boolean isEmpty() { + return !this.iterable.iterator().hasNext(); + } + + public final ImmutableList toList() { + return ImmutableList.copyOf(this.iterable); + } + + public final ImmutableList toSortedList(Comparator comparator) { + return Ordering.from(comparator).immutableSortedCopy(this.iterable); + } + + public final ImmutableSet toSet() { + return ImmutableSet.copyOf(this.iterable); + } + + public final ImmutableSortedSet toSortedSet(Comparator comparator) { + return ImmutableSortedSet.copyOf(comparator, this.iterable); + } + + public final ImmutableMap toMap(Function valueFunction) { + return Maps.toMap(this.iterable, valueFunction); + } + + public final ImmutableListMultimap index(Function keyFunction) { + return Multimaps.index(this.iterable, keyFunction); + } + + public final ImmutableMap uniqueIndex(Function keyFunction) { + return Maps.uniqueIndex(this.iterable, keyFunction); + } + + @GwtIncompatible(value="Array.newArray(Class, int)") + public final E[] toArray(Class type) { + return Iterables.toArray(this.iterable, type); + } + + public final > C copyInto(C collection) { + Preconditions.checkNotNull(collection); + if (this.iterable instanceof Collection) { + collection.addAll(Collections2.cast(this.iterable)); + } else { + for (E item : this.iterable) { + collection.add(item); + } + } + return collection; + } + + @Beta + public final String join(Joiner joiner) { + return joiner.join(this); + } + + public final E get(int position) { + return Iterables.get(this.iterable, position); + } + + private static class FromIterableFunction + implements Function, FluentIterable> { + private FromIterableFunction() { + } + + @Override + public FluentIterable apply(Iterable fromObject) { + return FluentIterable.from(fromObject); + } + } +} diff --git a/src/com/google/common/collect/ForwardingBlockingDeque.java b/src/com/google/common/collect/ForwardingBlockingDeque.java new file mode 100644 index 0000000..708b5a2 --- /dev/null +++ b/src/com/google/common/collect/ForwardingBlockingDeque.java @@ -0,0 +1,94 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ForwardingDeque; +import java.util.Collection; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.TimeUnit; + +public abstract class ForwardingBlockingDeque +extends ForwardingDeque +implements BlockingDeque { + protected ForwardingBlockingDeque() { + } + + @Override + protected abstract BlockingDeque delegate(); + + @Override + public int remainingCapacity() { + return this.delegate().remainingCapacity(); + } + + @Override + public void putFirst(E e) throws InterruptedException { + this.delegate().putFirst(e); + } + + @Override + public void putLast(E e) throws InterruptedException { + this.delegate().putLast(e); + } + + @Override + public boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().offerFirst(e, timeout, unit); + } + + @Override + public boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().offerLast(e, timeout, unit); + } + + @Override + public E takeFirst() throws InterruptedException { + return this.delegate().takeFirst(); + } + + @Override + public E takeLast() throws InterruptedException { + return this.delegate().takeLast(); + } + + @Override + public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().pollFirst(timeout, unit); + } + + @Override + public E pollLast(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().pollLast(timeout, unit); + } + + @Override + public void put(E e) throws InterruptedException { + this.delegate().put(e); + } + + @Override + public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().offer(e, timeout, unit); + } + + @Override + public E take() throws InterruptedException { + return this.delegate().take(); + } + + @Override + public E poll(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().poll(timeout, unit); + } + + @Override + public int drainTo(Collection c) { + return this.delegate().drainTo(c); + } + + @Override + public int drainTo(Collection c, int maxElements) { + return this.delegate().drainTo(c, maxElements); + } +} diff --git a/src/com/google/common/collect/ForwardingCollection.java b/src/com/google/common/collect/ForwardingCollection.java new file mode 100644 index 0000000..391d09b --- /dev/null +++ b/src/com/google/common/collect/ForwardingCollection.java @@ -0,0 +1,141 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.Iterators; +import com.google.common.collect.ObjectArrays; +import java.util.Collection; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingCollection +extends ForwardingObject +implements Collection { + protected ForwardingCollection() { + } + + @Override + protected abstract Collection delegate(); + + @Override + public Iterator iterator() { + return this.delegate().iterator(); + } + + @Override + public int size() { + return this.delegate().size(); + } + + @Override + public boolean removeAll(Collection collection) { + return this.delegate().removeAll(collection); + } + + @Override + public boolean isEmpty() { + return this.delegate().isEmpty(); + } + + @Override + public boolean contains(Object object) { + return this.delegate().contains(object); + } + + @Override + public boolean add(E element) { + return this.delegate().add(element); + } + + @Override + public boolean remove(Object object) { + return this.delegate().remove(object); + } + + @Override + public boolean containsAll(Collection collection) { + return this.delegate().containsAll(collection); + } + + @Override + public boolean addAll(Collection collection) { + return this.delegate().addAll(collection); + } + + @Override + public boolean retainAll(Collection collection) { + return this.delegate().retainAll(collection); + } + + @Override + public void clear() { + this.delegate().clear(); + } + + @Override + public Object[] toArray() { + return this.delegate().toArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.delegate().toArray(array); + } + + protected boolean standardContains(@Nullable Object object) { + return Iterators.contains(this.iterator(), object); + } + + protected boolean standardContainsAll(Collection collection) { + return Collections2.containsAllImpl(this, collection); + } + + protected boolean standardAddAll(Collection collection) { + return Iterators.addAll(this, collection.iterator()); + } + + protected boolean standardRemove(@Nullable Object object) { + Iterator iterator = this.iterator(); + while (iterator.hasNext()) { + if (!Objects.equal(iterator.next(), object)) continue; + iterator.remove(); + return true; + } + return false; + } + + protected boolean standardRemoveAll(Collection collection) { + return Iterators.removeAll(this.iterator(), collection); + } + + protected boolean standardRetainAll(Collection collection) { + return Iterators.retainAll(this.iterator(), collection); + } + + protected void standardClear() { + Iterators.clear(this.iterator()); + } + + protected boolean standardIsEmpty() { + return !this.iterator().hasNext(); + } + + protected String standardToString() { + return Collections2.toStringImpl(this); + } + + protected Object[] standardToArray() { + Object[] newArray = new Object[this.size()]; + return this.toArray(newArray); + } + + protected T[] standardToArray(T[] array) { + return ObjectArrays.toArrayImpl(this, array); + } +} diff --git a/src/com/google/common/collect/ForwardingConcurrentMap.java b/src/com/google/common/collect/ForwardingConcurrentMap.java new file mode 100644 index 0000000..8b02ec2 --- /dev/null +++ b/src/com/google/common/collect/ForwardingConcurrentMap.java @@ -0,0 +1,39 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingMap; +import java.util.concurrent.ConcurrentMap; + +@GwtCompatible +public abstract class ForwardingConcurrentMap +extends ForwardingMap +implements ConcurrentMap { + protected ForwardingConcurrentMap() { + } + + @Override + protected abstract ConcurrentMap delegate(); + + @Override + public V putIfAbsent(K key, V value) { + return this.delegate().putIfAbsent(key, value); + } + + @Override + public boolean remove(Object key, Object value) { + return this.delegate().remove(key, value); + } + + @Override + public V replace(K key, V value) { + return this.delegate().replace(key, value); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) { + return this.delegate().replace(key, oldValue, newValue); + } +} diff --git a/src/com/google/common/collect/ForwardingDeque.java b/src/com/google/common/collect/ForwardingDeque.java new file mode 100644 index 0000000..df59745 --- /dev/null +++ b/src/com/google/common/collect/ForwardingDeque.java @@ -0,0 +1,103 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ForwardingQueue; +import java.util.Deque; +import java.util.Iterator; + +public abstract class ForwardingDeque +extends ForwardingQueue +implements Deque { + protected ForwardingDeque() { + } + + @Override + protected abstract Deque delegate(); + + @Override + public void addFirst(E e) { + this.delegate().addFirst(e); + } + + @Override + public void addLast(E e) { + this.delegate().addLast(e); + } + + @Override + public Iterator descendingIterator() { + return this.delegate().descendingIterator(); + } + + @Override + public E getFirst() { + return this.delegate().getFirst(); + } + + @Override + public E getLast() { + return this.delegate().getLast(); + } + + @Override + public boolean offerFirst(E e) { + return this.delegate().offerFirst(e); + } + + @Override + public boolean offerLast(E e) { + return this.delegate().offerLast(e); + } + + @Override + public E peekFirst() { + return this.delegate().peekFirst(); + } + + @Override + public E peekLast() { + return this.delegate().peekLast(); + } + + @Override + public E pollFirst() { + return this.delegate().pollFirst(); + } + + @Override + public E pollLast() { + return this.delegate().pollLast(); + } + + @Override + public E pop() { + return this.delegate().pop(); + } + + @Override + public void push(E e) { + this.delegate().push(e); + } + + @Override + public E removeFirst() { + return this.delegate().removeFirst(); + } + + @Override + public E removeLast() { + return this.delegate().removeLast(); + } + + @Override + public boolean removeFirstOccurrence(Object o) { + return this.delegate().removeFirstOccurrence(o); + } + + @Override + public boolean removeLastOccurrence(Object o) { + return this.delegate().removeLastOccurrence(o); + } +} diff --git a/src/com/google/common/collect/ForwardingImmutableCollection.java b/src/com/google/common/collect/ForwardingImmutableCollection.java new file mode 100644 index 0000000..7a9e336 --- /dev/null +++ b/src/com/google/common/collect/ForwardingImmutableCollection.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +class ForwardingImmutableCollection { + private ForwardingImmutableCollection() { + } +} diff --git a/src/com/google/common/collect/ForwardingImmutableList.java b/src/com/google/common/collect/ForwardingImmutableList.java new file mode 100644 index 0000000..3c30876 --- /dev/null +++ b/src/com/google/common/collect/ForwardingImmutableList.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableList { + private ForwardingImmutableList() { + } +} diff --git a/src/com/google/common/collect/ForwardingImmutableMap.java b/src/com/google/common/collect/ForwardingImmutableMap.java new file mode 100644 index 0000000..4ddefe4 --- /dev/null +++ b/src/com/google/common/collect/ForwardingImmutableMap.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableMap { + private ForwardingImmutableMap() { + } +} diff --git a/src/com/google/common/collect/ForwardingImmutableSet.java b/src/com/google/common/collect/ForwardingImmutableSet.java new file mode 100644 index 0000000..80af387 --- /dev/null +++ b/src/com/google/common/collect/ForwardingImmutableSet.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableSet { + private ForwardingImmutableSet() { + } +} diff --git a/src/com/google/common/collect/ForwardingIterator.java b/src/com/google/common/collect/ForwardingIterator.java new file mode 100644 index 0000000..a821547 --- /dev/null +++ b/src/com/google/common/collect/ForwardingIterator.java @@ -0,0 +1,34 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingObject; +import java.util.Iterator; + +@GwtCompatible +public abstract class ForwardingIterator +extends ForwardingObject +implements Iterator { + protected ForwardingIterator() { + } + + @Override + protected abstract Iterator delegate(); + + @Override + public boolean hasNext() { + return this.delegate().hasNext(); + } + + @Override + public T next() { + return (T)this.delegate().next(); + } + + @Override + public void remove() { + this.delegate().remove(); + } +} diff --git a/src/com/google/common/collect/ForwardingList.java b/src/com/google/common/collect/ForwardingList.java new file mode 100644 index 0000000..b87c8ad --- /dev/null +++ b/src/com/google/common/collect/ForwardingList.java @@ -0,0 +1,130 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingList +extends ForwardingCollection +implements List { + protected ForwardingList() { + } + + @Override + protected abstract List delegate(); + + @Override + public void add(int index, E element) { + this.delegate().add(index, element); + } + + @Override + public boolean addAll(int index, Collection elements) { + return this.delegate().addAll(index, elements); + } + + @Override + public E get(int index) { + return this.delegate().get(index); + } + + @Override + public int indexOf(Object element) { + return this.delegate().indexOf(element); + } + + @Override + public int lastIndexOf(Object element) { + return this.delegate().lastIndexOf(element); + } + + @Override + public ListIterator listIterator() { + return this.delegate().listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return this.delegate().listIterator(index); + } + + @Override + public E remove(int index) { + return this.delegate().remove(index); + } + + @Override + public E set(int index, E element) { + return this.delegate().set(index, element); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return this.delegate().subList(fromIndex, toIndex); + } + + @Override + public boolean equals(@Nullable Object object) { + return object == this || this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } + + protected boolean standardAdd(E element) { + this.add(this.size(), element); + return true; + } + + protected boolean standardAddAll(int index, Iterable elements) { + return Lists.addAllImpl(this, index, elements); + } + + protected int standardIndexOf(@Nullable Object element) { + return Lists.indexOfImpl(this, element); + } + + protected int standardLastIndexOf(@Nullable Object element) { + return Lists.lastIndexOfImpl(this, element); + } + + protected Iterator standardIterator() { + return this.listIterator(); + } + + protected ListIterator standardListIterator() { + return this.listIterator(0); + } + + @Beta + protected ListIterator standardListIterator(int start) { + return Lists.listIteratorImpl(this, start); + } + + @Beta + protected List standardSubList(int fromIndex, int toIndex) { + return Lists.subListImpl(this, fromIndex, toIndex); + } + + @Beta + protected boolean standardEquals(@Nullable Object object) { + return Lists.equalsImpl(this, object); + } + + @Beta + protected int standardHashCode() { + return Lists.hashCodeImpl(this); + } +} diff --git a/src/com/google/common/collect/ForwardingListIterator.java b/src/com/google/common/collect/ForwardingListIterator.java new file mode 100644 index 0000000..eda3293 --- /dev/null +++ b/src/com/google/common/collect/ForwardingListIterator.java @@ -0,0 +1,49 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingIterator; +import java.util.ListIterator; + +@GwtCompatible +public abstract class ForwardingListIterator +extends ForwardingIterator +implements ListIterator { + protected ForwardingListIterator() { + } + + @Override + protected abstract ListIterator delegate(); + + @Override + public void add(E element) { + this.delegate().add(element); + } + + @Override + public boolean hasPrevious() { + return this.delegate().hasPrevious(); + } + + @Override + public int nextIndex() { + return this.delegate().nextIndex(); + } + + @Override + public E previous() { + return this.delegate().previous(); + } + + @Override + public int previousIndex() { + return this.delegate().previousIndex(); + } + + @Override + public void set(E element) { + this.delegate().set(element); + } +} diff --git a/src/com/google/common/collect/ForwardingListMultimap.java b/src/com/google/common/collect/ForwardingListMultimap.java new file mode 100644 index 0000000..5925649 --- /dev/null +++ b/src/com/google/common/collect/ForwardingListMultimap.java @@ -0,0 +1,36 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingMultimap; +import com.google.common.collect.ListMultimap; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingListMultimap +extends ForwardingMultimap +implements ListMultimap { + protected ForwardingListMultimap() { + } + + @Override + protected abstract ListMultimap delegate(); + + @Override + public List get(@Nullable K key) { + return this.delegate().get(key); + } + + @Override + public List removeAll(@Nullable Object key) { + return this.delegate().removeAll(key); + } + + @Override + public List replaceValues(K key, Iterable values) { + return this.delegate().replaceValues(key, values); + } +} diff --git a/src/com/google/common/collect/ForwardingMap.java b/src/com/google/common/collect/ForwardingMap.java new file mode 100644 index 0000000..40e7fb4 --- /dev/null +++ b/src/com/google/common/collect/ForwardingMap.java @@ -0,0 +1,169 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingMap +extends ForwardingObject +implements Map { + protected ForwardingMap() { + } + + @Override + protected abstract Map delegate(); + + @Override + public int size() { + return this.delegate().size(); + } + + @Override + public boolean isEmpty() { + return this.delegate().isEmpty(); + } + + @Override + public V remove(Object object) { + return this.delegate().remove(object); + } + + @Override + public void clear() { + this.delegate().clear(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.delegate().containsKey(key); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.delegate().containsValue(value); + } + + @Override + public V get(@Nullable Object key) { + return this.delegate().get(key); + } + + @Override + public V put(K key, V value) { + return this.delegate().put(key, value); + } + + @Override + public void putAll(Map map) { + this.delegate().putAll(map); + } + + @Override + public Set keySet() { + return this.delegate().keySet(); + } + + @Override + public Collection values() { + return this.delegate().values(); + } + + @Override + public Set> entrySet() { + return this.delegate().entrySet(); + } + + @Override + public boolean equals(@Nullable Object object) { + return object == this || this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } + + protected void standardPutAll(Map map) { + Maps.putAllImpl(this, map); + } + + @Beta + protected V standardRemove(@Nullable Object key) { + Iterator> entryIterator = this.entrySet().iterator(); + while (entryIterator.hasNext()) { + Map.Entry entry = entryIterator.next(); + if (!Objects.equal(entry.getKey(), key)) continue; + V value = entry.getValue(); + entryIterator.remove(); + return value; + } + return null; + } + + protected void standardClear() { + Iterators.clear(this.entrySet().iterator()); + } + + @Beta + protected boolean standardContainsKey(@Nullable Object key) { + return Maps.containsKeyImpl(this, key); + } + + protected boolean standardContainsValue(@Nullable Object value) { + return Maps.containsValueImpl(this, value); + } + + protected boolean standardIsEmpty() { + return !this.entrySet().iterator().hasNext(); + } + + protected boolean standardEquals(@Nullable Object object) { + return Maps.equalsImpl(this, object); + } + + protected int standardHashCode() { + return Sets.hashCodeImpl(this.entrySet()); + } + + protected String standardToString() { + return Maps.toStringImpl(this); + } + + @Beta + protected abstract class StandardEntrySet + extends Maps.EntrySet { + @Override + Map map() { + return ForwardingMap.this; + } + } + + @Beta + protected class StandardValues + extends Maps.Values { + public StandardValues() { + super(ForwardingMap.this); + } + } + + @Beta + protected class StandardKeySet + extends Maps.KeySet { + public StandardKeySet() { + super(ForwardingMap.this); + } + } +} diff --git a/src/com/google/common/collect/ForwardingMapEntry.java b/src/com/google/common/collect/ForwardingMapEntry.java new file mode 100644 index 0000000..11df3b1 --- /dev/null +++ b/src/com/google/common/collect/ForwardingMapEntry.java @@ -0,0 +1,68 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingObject; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingMapEntry +extends ForwardingObject +implements Map.Entry { + protected ForwardingMapEntry() { + } + + @Override + protected abstract Map.Entry delegate(); + + @Override + public K getKey() { + return this.delegate().getKey(); + } + + @Override + public V getValue() { + return this.delegate().getValue(); + } + + @Override + public V setValue(V value) { + return this.delegate().setValue(value); + } + + @Override + public boolean equals(@Nullable Object object) { + return this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } + + protected boolean standardEquals(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry that = (Map.Entry)object; + return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue()); + } + return false; + } + + protected int standardHashCode() { + K k = this.getKey(); + V v = this.getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + @Beta + protected String standardToString() { + String string = String.valueOf(String.valueOf(this.getKey())); + String string2 = String.valueOf(String.valueOf(this.getValue())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append("=").append(string2).toString(); + } +} diff --git a/src/com/google/common/collect/ForwardingMultimap.java b/src/com/google/common/collect/ForwardingMultimap.java new file mode 100644 index 0000000..6d5632c --- /dev/null +++ b/src/com/google/common/collect/ForwardingMultimap.java @@ -0,0 +1,124 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingMultimap +extends ForwardingObject +implements Multimap { + protected ForwardingMultimap() { + } + + @Override + protected abstract Multimap delegate(); + + @Override + public Map> asMap() { + return this.delegate().asMap(); + } + + @Override + public void clear() { + this.delegate().clear(); + } + + @Override + public boolean containsEntry(@Nullable Object key, @Nullable Object value) { + return this.delegate().containsEntry(key, value); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.delegate().containsKey(key); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.delegate().containsValue(value); + } + + @Override + public Collection> entries() { + return this.delegate().entries(); + } + + @Override + public Collection get(@Nullable K key) { + return this.delegate().get(key); + } + + @Override + public boolean isEmpty() { + return this.delegate().isEmpty(); + } + + @Override + public Multiset keys() { + return this.delegate().keys(); + } + + @Override + public Set keySet() { + return this.delegate().keySet(); + } + + @Override + public boolean put(K key, V value) { + return this.delegate().put(key, value); + } + + @Override + public boolean putAll(K key, Iterable values) { + return this.delegate().putAll(key, values); + } + + @Override + public boolean putAll(Multimap multimap) { + return this.delegate().putAll(multimap); + } + + @Override + public boolean remove(@Nullable Object key, @Nullable Object value) { + return this.delegate().remove(key, value); + } + + @Override + public Collection removeAll(@Nullable Object key) { + return this.delegate().removeAll(key); + } + + @Override + public Collection replaceValues(K key, Iterable values) { + return this.delegate().replaceValues(key, values); + } + + @Override + public int size() { + return this.delegate().size(); + } + + @Override + public Collection values() { + return this.delegate().values(); + } + + @Override + public boolean equals(@Nullable Object object) { + return object == this || this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } +} diff --git a/src/com/google/common/collect/ForwardingMultiset.java b/src/com/google/common/collect/ForwardingMultiset.java new file mode 100644 index 0000000..81d96c5 --- /dev/null +++ b/src/com/google/common/collect/ForwardingMultiset.java @@ -0,0 +1,155 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingMultiset +extends ForwardingCollection +implements Multiset { + protected ForwardingMultiset() { + } + + @Override + protected abstract Multiset delegate(); + + @Override + public int count(Object element) { + return this.delegate().count(element); + } + + @Override + public int add(E element, int occurrences) { + return this.delegate().add(element, occurrences); + } + + @Override + public int remove(Object element, int occurrences) { + return this.delegate().remove(element, occurrences); + } + + @Override + public Set elementSet() { + return this.delegate().elementSet(); + } + + @Override + public Set> entrySet() { + return this.delegate().entrySet(); + } + + @Override + public boolean equals(@Nullable Object object) { + return object == this || this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } + + @Override + public int setCount(E element, int count) { + return this.delegate().setCount(element, count); + } + + @Override + public boolean setCount(E element, int oldCount, int newCount) { + return this.delegate().setCount(element, oldCount, newCount); + } + + @Override + protected boolean standardContains(@Nullable Object object) { + return this.count(object) > 0; + } + + @Override + protected void standardClear() { + Iterators.clear(this.entrySet().iterator()); + } + + @Beta + protected int standardCount(@Nullable Object object) { + for (Multiset.Entry entry : this.entrySet()) { + if (!Objects.equal(entry.getElement(), object)) continue; + return entry.getCount(); + } + return 0; + } + + protected boolean standardAdd(E element) { + this.add(element, 1); + return true; + } + + @Override + @Beta + protected boolean standardAddAll(Collection elementsToAdd) { + return Multisets.addAllImpl(this, elementsToAdd); + } + + @Override + protected boolean standardRemove(Object element) { + return this.remove(element, 1) > 0; + } + + @Override + protected boolean standardRemoveAll(Collection elementsToRemove) { + return Multisets.removeAllImpl(this, elementsToRemove); + } + + @Override + protected boolean standardRetainAll(Collection elementsToRetain) { + return Multisets.retainAllImpl(this, elementsToRetain); + } + + protected int standardSetCount(E element, int count) { + return Multisets.setCountImpl(this, element, count); + } + + protected boolean standardSetCount(E element, int oldCount, int newCount) { + return Multisets.setCountImpl(this, element, oldCount, newCount); + } + + protected Iterator standardIterator() { + return Multisets.iteratorImpl(this); + } + + protected int standardSize() { + return Multisets.sizeImpl(this); + } + + protected boolean standardEquals(@Nullable Object object) { + return Multisets.equalsImpl(this, object); + } + + protected int standardHashCode() { + return this.entrySet().hashCode(); + } + + @Override + protected String standardToString() { + return this.entrySet().toString(); + } + + @Beta + protected class StandardElementSet + extends Multisets.ElementSet { + @Override + Multiset multiset() { + return ForwardingMultiset.this; + } + } +} diff --git a/src/com/google/common/collect/ForwardingNavigableMap.java b/src/com/google/common/collect/ForwardingNavigableMap.java new file mode 100644 index 0000000..6206dc6 --- /dev/null +++ b/src/com/google/common/collect/ForwardingNavigableMap.java @@ -0,0 +1,254 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ForwardingSortedMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.SortedMap; + +public abstract class ForwardingNavigableMap +extends ForwardingSortedMap +implements NavigableMap { + protected ForwardingNavigableMap() { + } + + @Override + protected abstract NavigableMap delegate(); + + @Override + public Map.Entry lowerEntry(K key) { + return this.delegate().lowerEntry(key); + } + + protected Map.Entry standardLowerEntry(K key) { + return this.headMap(key, false).lastEntry(); + } + + @Override + public K lowerKey(K key) { + return this.delegate().lowerKey(key); + } + + protected K standardLowerKey(K key) { + return Maps.keyOrNull(this.lowerEntry(key)); + } + + @Override + public Map.Entry floorEntry(K key) { + return this.delegate().floorEntry(key); + } + + protected Map.Entry standardFloorEntry(K key) { + return this.headMap(key, true).lastEntry(); + } + + @Override + public K floorKey(K key) { + return this.delegate().floorKey(key); + } + + protected K standardFloorKey(K key) { + return Maps.keyOrNull(this.floorEntry(key)); + } + + @Override + public Map.Entry ceilingEntry(K key) { + return this.delegate().ceilingEntry(key); + } + + protected Map.Entry standardCeilingEntry(K key) { + return this.tailMap(key, true).firstEntry(); + } + + @Override + public K ceilingKey(K key) { + return this.delegate().ceilingKey(key); + } + + protected K standardCeilingKey(K key) { + return Maps.keyOrNull(this.ceilingEntry(key)); + } + + @Override + public Map.Entry higherEntry(K key) { + return this.delegate().higherEntry(key); + } + + protected Map.Entry standardHigherEntry(K key) { + return this.tailMap(key, false).firstEntry(); + } + + @Override + public K higherKey(K key) { + return this.delegate().higherKey(key); + } + + protected K standardHigherKey(K key) { + return Maps.keyOrNull(this.higherEntry(key)); + } + + @Override + public Map.Entry firstEntry() { + return this.delegate().firstEntry(); + } + + protected Map.Entry standardFirstEntry() { + return Iterables.getFirst(this.entrySet(), null); + } + + protected K standardFirstKey() { + Map.Entry entry = this.firstEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + @Override + public Map.Entry lastEntry() { + return this.delegate().lastEntry(); + } + + protected Map.Entry standardLastEntry() { + return Iterables.getFirst(this.descendingMap().entrySet(), null); + } + + protected K standardLastKey() { + Map.Entry entry = this.lastEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + @Override + public Map.Entry pollFirstEntry() { + return this.delegate().pollFirstEntry(); + } + + protected Map.Entry standardPollFirstEntry() { + return Iterators.pollNext(this.entrySet().iterator()); + } + + @Override + public Map.Entry pollLastEntry() { + return this.delegate().pollLastEntry(); + } + + protected Map.Entry standardPollLastEntry() { + return Iterators.pollNext(this.descendingMap().entrySet().iterator()); + } + + @Override + public NavigableMap descendingMap() { + return this.delegate().descendingMap(); + } + + @Override + public NavigableSet navigableKeySet() { + return this.delegate().navigableKeySet(); + } + + @Override + public NavigableSet descendingKeySet() { + return this.delegate().descendingKeySet(); + } + + @Beta + protected NavigableSet standardDescendingKeySet() { + return this.descendingMap().navigableKeySet(); + } + + @Override + protected SortedMap standardSubMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return this.delegate().subMap(fromKey, fromInclusive, toKey, toInclusive); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return this.delegate().headMap(toKey, inclusive); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return this.delegate().tailMap(fromKey, inclusive); + } + + protected SortedMap standardHeadMap(K toKey) { + return this.headMap(toKey, false); + } + + protected SortedMap standardTailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Beta + protected class StandardNavigableKeySet + extends Maps.NavigableKeySet { + public StandardNavigableKeySet() { + super(ForwardingNavigableMap.this); + } + } + + @Beta + protected class StandardDescendingMap + extends Maps.DescendingMap { + @Override + NavigableMap forward() { + return ForwardingNavigableMap.this; + } + + @Override + protected Iterator> entryIterator() { + return new Iterator>(){ + private Map.Entry toRemove = null; + private Map.Entry nextOrNull = StandardDescendingMap.this.forward().lastEntry(); + + @Override + public boolean hasNext() { + return this.nextOrNull != null; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + try { + Map.Entry entry = this.nextOrNull; + return entry; + } + finally { + this.toRemove = this.nextOrNull; + this.nextOrNull = StandardDescendingMap.this.forward().lowerEntry(this.nextOrNull.getKey()); + } + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.toRemove != null); + StandardDescendingMap.this.forward().remove(this.toRemove.getKey()); + this.toRemove = null; + } + }; + } + } +} diff --git a/src/com/google/common/collect/ForwardingNavigableSet.java b/src/com/google/common/collect/ForwardingNavigableSet.java new file mode 100644 index 0000000..79b5210 --- /dev/null +++ b/src/com/google/common/collect/ForwardingNavigableSet.java @@ -0,0 +1,135 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ForwardingSortedSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Sets; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; + +public abstract class ForwardingNavigableSet +extends ForwardingSortedSet +implements NavigableSet { + protected ForwardingNavigableSet() { + } + + @Override + protected abstract NavigableSet delegate(); + + @Override + public E lower(E e) { + return this.delegate().lower(e); + } + + protected E standardLower(E e) { + return Iterators.getNext(this.headSet(e, false).descendingIterator(), null); + } + + @Override + public E floor(E e) { + return this.delegate().floor(e); + } + + protected E standardFloor(E e) { + return Iterators.getNext(this.headSet(e, true).descendingIterator(), null); + } + + @Override + public E ceiling(E e) { + return this.delegate().ceiling(e); + } + + protected E standardCeiling(E e) { + return Iterators.getNext(this.tailSet(e, true).iterator(), null); + } + + @Override + public E higher(E e) { + return this.delegate().higher(e); + } + + protected E standardHigher(E e) { + return Iterators.getNext(this.tailSet(e, false).iterator(), null); + } + + @Override + public E pollFirst() { + return this.delegate().pollFirst(); + } + + protected E standardPollFirst() { + return Iterators.pollNext(this.iterator()); + } + + @Override + public E pollLast() { + return this.delegate().pollLast(); + } + + protected E standardPollLast() { + return Iterators.pollNext(this.descendingIterator()); + } + + protected E standardFirst() { + return this.iterator().next(); + } + + protected E standardLast() { + return this.descendingIterator().next(); + } + + @Override + public NavigableSet descendingSet() { + return this.delegate().descendingSet(); + } + + @Override + public Iterator descendingIterator() { + return this.delegate().descendingIterator(); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return this.delegate().subSet(fromElement, fromInclusive, toElement, toInclusive); + } + + @Beta + protected NavigableSet standardSubSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return this.tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive); + } + + @Override + protected SortedSet standardSubSet(E fromElement, E toElement) { + return this.subSet(fromElement, true, toElement, false); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return this.delegate().headSet(toElement, inclusive); + } + + protected SortedSet standardHeadSet(E toElement) { + return this.headSet(toElement, false); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return this.delegate().tailSet(fromElement, inclusive); + } + + protected SortedSet standardTailSet(E fromElement) { + return this.tailSet(fromElement, true); + } + + @Beta + protected class StandardDescendingSet + extends Sets.DescendingSet { + public StandardDescendingSet() { + super(ForwardingNavigableSet.this); + } + } +} diff --git a/src/com/google/common/collect/ForwardingObject.java b/src/com/google/common/collect/ForwardingObject.java new file mode 100644 index 0000000..7a450e5 --- /dev/null +++ b/src/com/google/common/collect/ForwardingObject.java @@ -0,0 +1,18 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public abstract class ForwardingObject { + protected ForwardingObject() { + } + + protected abstract Object delegate(); + + public String toString() { + return this.delegate().toString(); + } +} diff --git a/src/com/google/common/collect/ForwardingQueue.java b/src/com/google/common/collect/ForwardingQueue.java new file mode 100644 index 0000000..b402bbb --- /dev/null +++ b/src/com/google/common/collect/ForwardingQueue.java @@ -0,0 +1,72 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingCollection; +import java.util.NoSuchElementException; +import java.util.Queue; + +@GwtCompatible +public abstract class ForwardingQueue +extends ForwardingCollection +implements Queue { + protected ForwardingQueue() { + } + + @Override + protected abstract Queue delegate(); + + @Override + public boolean offer(E o) { + return this.delegate().offer(o); + } + + @Override + public E poll() { + return this.delegate().poll(); + } + + @Override + public E remove() { + return this.delegate().remove(); + } + + @Override + public E peek() { + return this.delegate().peek(); + } + + @Override + public E element() { + return this.delegate().element(); + } + + protected boolean standardOffer(E e) { + try { + return this.add(e); + } + catch (IllegalStateException caught) { + return false; + } + } + + protected E standardPeek() { + try { + return this.element(); + } + catch (NoSuchElementException caught) { + return null; + } + } + + protected E standardPoll() { + try { + return this.remove(); + } + catch (NoSuchElementException caught) { + return null; + } + } +} diff --git a/src/com/google/common/collect/ForwardingSet.java b/src/com/google/common/collect/ForwardingSet.java new file mode 100644 index 0000000..7694836 --- /dev/null +++ b/src/com/google/common/collect/ForwardingSet.java @@ -0,0 +1,46 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingSet +extends ForwardingCollection +implements Set { + protected ForwardingSet() { + } + + @Override + protected abstract Set delegate(); + + @Override + public boolean equals(@Nullable Object object) { + return object == this || this.delegate().equals(object); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } + + @Override + protected boolean standardRemoveAll(Collection collection) { + return Sets.removeAllImpl(this, Preconditions.checkNotNull(collection)); + } + + protected boolean standardEquals(@Nullable Object object) { + return Sets.equalsImpl(this, object); + } + + protected int standardHashCode() { + return Sets.hashCodeImpl(this); + } +} diff --git a/src/com/google/common/collect/ForwardingSetMultimap.java b/src/com/google/common/collect/ForwardingSetMultimap.java new file mode 100644 index 0000000..e2593b9 --- /dev/null +++ b/src/com/google/common/collect/ForwardingSetMultimap.java @@ -0,0 +1,39 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingMultimap; +import com.google.common.collect.SetMultimap; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingSetMultimap +extends ForwardingMultimap +implements SetMultimap { + @Override + protected abstract SetMultimap delegate(); + + @Override + public Set> entries() { + return this.delegate().entries(); + } + + @Override + public Set get(@Nullable K key) { + return this.delegate().get(key); + } + + @Override + public Set removeAll(@Nullable Object key) { + return this.delegate().removeAll(key); + } + + @Override + public Set replaceValues(K key, Iterable values) { + return this.delegate().replaceValues(key, values); + } +} diff --git a/src/com/google/common/collect/ForwardingSortedMap.java b/src/com/google/common/collect/ForwardingSortedMap.java new file mode 100644 index 0000000..aace637 --- /dev/null +++ b/src/com/google/common/collect/ForwardingSortedMap.java @@ -0,0 +1,96 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.Maps; +import java.util.Comparator; +import java.util.NoSuchElementException; +import java.util.SortedMap; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingSortedMap +extends ForwardingMap +implements SortedMap { + protected ForwardingSortedMap() { + } + + @Override + protected abstract SortedMap delegate(); + + @Override + public Comparator comparator() { + return this.delegate().comparator(); + } + + @Override + public K firstKey() { + return this.delegate().firstKey(); + } + + @Override + public SortedMap headMap(K toKey) { + return this.delegate().headMap(toKey); + } + + @Override + public K lastKey() { + return this.delegate().lastKey(); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return this.delegate().subMap(fromKey, toKey); + } + + @Override + public SortedMap tailMap(K fromKey) { + return this.delegate().tailMap(fromKey); + } + + private int unsafeCompare(Object k1, Object k2) { + Comparator comparator = this.comparator(); + if (comparator == null) { + return ((Comparable)k1).compareTo(k2); + } + return comparator.compare(k1, k2); + } + + @Override + @Beta + protected boolean standardContainsKey(@Nullable Object key) { + try { + ForwardingSortedMap self = this; + Object ceilingKey = self.tailMap(key).firstKey(); + return this.unsafeCompare(ceilingKey, key) == 0; + } + catch (ClassCastException e) { + return false; + } + catch (NoSuchElementException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + } + + @Beta + protected SortedMap standardSubMap(K fromKey, K toKey) { + Preconditions.checkArgument(this.unsafeCompare(fromKey, toKey) <= 0, "fromKey must be <= toKey"); + return this.tailMap(fromKey).headMap(toKey); + } + + @Beta + protected class StandardKeySet + extends Maps.SortedKeySet { + public StandardKeySet() { + super(ForwardingSortedMap.this); + } + } +} diff --git a/src/com/google/common/collect/ForwardingSortedMultiset.java b/src/com/google/common/collect/ForwardingSortedMultiset.java new file mode 100644 index 0000000..237c701 --- /dev/null +++ b/src/com/google/common/collect/ForwardingSortedMultiset.java @@ -0,0 +1,138 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.DescendingMultiset; +import com.google.common.collect.ForwardingMultiset; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.SortedMultiset; +import com.google.common.collect.SortedMultisets; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; + +@Beta +@GwtCompatible(emulated=true) +public abstract class ForwardingSortedMultiset +extends ForwardingMultiset +implements SortedMultiset { + protected ForwardingSortedMultiset() { + } + + @Override + protected abstract SortedMultiset delegate(); + + @Override + public NavigableSet elementSet() { + return (NavigableSet)super.elementSet(); + } + + @Override + public Comparator comparator() { + return this.delegate().comparator(); + } + + @Override + public SortedMultiset descendingMultiset() { + return this.delegate().descendingMultiset(); + } + + @Override + public Multiset.Entry firstEntry() { + return this.delegate().firstEntry(); + } + + protected Multiset.Entry standardFirstEntry() { + Iterator entryIterator = this.entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = entryIterator.next(); + return Multisets.immutableEntry(entry.getElement(), entry.getCount()); + } + + @Override + public Multiset.Entry lastEntry() { + return this.delegate().lastEntry(); + } + + protected Multiset.Entry standardLastEntry() { + Iterator> entryIterator = this.descendingMultiset().entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = entryIterator.next(); + return Multisets.immutableEntry(entry.getElement(), entry.getCount()); + } + + @Override + public Multiset.Entry pollFirstEntry() { + return this.delegate().pollFirstEntry(); + } + + protected Multiset.Entry standardPollFirstEntry() { + Iterator entryIterator = this.entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = entryIterator.next(); + entry = Multisets.immutableEntry(entry.getElement(), entry.getCount()); + entryIterator.remove(); + return entry; + } + + @Override + public Multiset.Entry pollLastEntry() { + return this.delegate().pollLastEntry(); + } + + protected Multiset.Entry standardPollLastEntry() { + Iterator> entryIterator = this.descendingMultiset().entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = entryIterator.next(); + entry = Multisets.immutableEntry(entry.getElement(), entry.getCount()); + entryIterator.remove(); + return entry; + } + + @Override + public SortedMultiset headMultiset(E upperBound, BoundType boundType) { + return this.delegate().headMultiset(upperBound, boundType); + } + + @Override + public SortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) { + return this.delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType); + } + + protected SortedMultiset standardSubMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) { + return this.tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType); + } + + @Override + public SortedMultiset tailMultiset(E lowerBound, BoundType boundType) { + return this.delegate().tailMultiset(lowerBound, boundType); + } + + protected abstract class StandardDescendingMultiset + extends DescendingMultiset { + @Override + SortedMultiset forwardMultiset() { + return ForwardingSortedMultiset.this; + } + } + + protected class StandardElementSet + extends SortedMultisets.NavigableElementSet { + public StandardElementSet() { + super(ForwardingSortedMultiset.this); + } + } +} diff --git a/src/com/google/common/collect/ForwardingSortedSet.java b/src/com/google/common/collect/ForwardingSortedSet.java new file mode 100644 index 0000000..5141a33 --- /dev/null +++ b/src/com/google/common/collect/ForwardingSortedSet.java @@ -0,0 +1,104 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingSet; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingSortedSet +extends ForwardingSet +implements SortedSet { + protected ForwardingSortedSet() { + } + + @Override + protected abstract SortedSet delegate(); + + @Override + public Comparator comparator() { + return this.delegate().comparator(); + } + + @Override + public E first() { + return this.delegate().first(); + } + + @Override + public SortedSet headSet(E toElement) { + return this.delegate().headSet(toElement); + } + + @Override + public E last() { + return this.delegate().last(); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return this.delegate().subSet(fromElement, toElement); + } + + @Override + public SortedSet tailSet(E fromElement) { + return this.delegate().tailSet(fromElement); + } + + private int unsafeCompare(Object o1, Object o2) { + Comparator comparator = this.comparator(); + return comparator == null ? ((Comparable)o1).compareTo(o2) : comparator.compare(o1, o2); + } + + @Override + @Beta + protected boolean standardContains(@Nullable Object object) { + try { + ForwardingSortedSet self = this; + Object ceiling = self.tailSet(object).first(); + return this.unsafeCompare(ceiling, object) == 0; + } + catch (ClassCastException e) { + return false; + } + catch (NoSuchElementException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + } + + @Override + @Beta + protected boolean standardRemove(@Nullable Object object) { + try { + Object ceiling; + ForwardingSortedSet self = this; + Iterator iterator = self.tailSet(object).iterator(); + if (iterator.hasNext() && this.unsafeCompare(ceiling = iterator.next(), object) == 0) { + iterator.remove(); + return true; + } + } + catch (ClassCastException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + return false; + } + + @Beta + protected SortedSet standardSubSet(E fromElement, E toElement) { + return this.tailSet(fromElement).headSet(toElement); + } +} diff --git a/src/com/google/common/collect/ForwardingSortedSetMultimap.java b/src/com/google/common/collect/ForwardingSortedSetMultimap.java new file mode 100644 index 0000000..4a6246f --- /dev/null +++ b/src/com/google/common/collect/ForwardingSortedSetMultimap.java @@ -0,0 +1,42 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingSetMultimap; +import com.google.common.collect.SortedSetMultimap; +import java.util.Comparator; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ForwardingSortedSetMultimap +extends ForwardingSetMultimap +implements SortedSetMultimap { + protected ForwardingSortedSetMultimap() { + } + + @Override + protected abstract SortedSetMultimap delegate(); + + @Override + public SortedSet get(@Nullable K key) { + return this.delegate().get(key); + } + + @Override + public SortedSet removeAll(@Nullable Object key) { + return this.delegate().removeAll(key); + } + + @Override + public SortedSet replaceValues(K key, Iterable values) { + return this.delegate().replaceValues(key, values); + } + + @Override + public Comparator valueComparator() { + return this.delegate().valueComparator(); + } +} diff --git a/src/com/google/common/collect/ForwardingTable.java b/src/com/google/common/collect/ForwardingTable.java new file mode 100644 index 0000000..8a4a19e --- /dev/null +++ b/src/com/google/common/collect/ForwardingTable.java @@ -0,0 +1,127 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.Table; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +@GwtCompatible +public abstract class ForwardingTable +extends ForwardingObject +implements Table { + protected ForwardingTable() { + } + + @Override + protected abstract Table delegate(); + + @Override + public Set> cellSet() { + return this.delegate().cellSet(); + } + + @Override + public void clear() { + this.delegate().clear(); + } + + @Override + public Map column(C columnKey) { + return this.delegate().column(columnKey); + } + + @Override + public Set columnKeySet() { + return this.delegate().columnKeySet(); + } + + @Override + public Map> columnMap() { + return this.delegate().columnMap(); + } + + @Override + public boolean contains(Object rowKey, Object columnKey) { + return this.delegate().contains(rowKey, columnKey); + } + + @Override + public boolean containsColumn(Object columnKey) { + return this.delegate().containsColumn(columnKey); + } + + @Override + public boolean containsRow(Object rowKey) { + return this.delegate().containsRow(rowKey); + } + + @Override + public boolean containsValue(Object value) { + return this.delegate().containsValue(value); + } + + @Override + public V get(Object rowKey, Object columnKey) { + return this.delegate().get(rowKey, columnKey); + } + + @Override + public boolean isEmpty() { + return this.delegate().isEmpty(); + } + + @Override + public V put(R rowKey, C columnKey, V value) { + return this.delegate().put(rowKey, columnKey, value); + } + + @Override + public void putAll(Table table) { + this.delegate().putAll(table); + } + + @Override + public V remove(Object rowKey, Object columnKey) { + return this.delegate().remove(rowKey, columnKey); + } + + @Override + public Map row(R rowKey) { + return this.delegate().row(rowKey); + } + + @Override + public Set rowKeySet() { + return this.delegate().rowKeySet(); + } + + @Override + public Map> rowMap() { + return this.delegate().rowMap(); + } + + @Override + public int size() { + return this.delegate().size(); + } + + @Override + public Collection values() { + return this.delegate().values(); + } + + @Override + public boolean equals(Object obj) { + return obj == this || this.delegate().equals(obj); + } + + @Override + public int hashCode() { + return this.delegate().hashCode(); + } +} diff --git a/src/com/google/common/collect/GeneralRange.java b/src/com/google/common/collect/GeneralRange.java new file mode 100644 index 0000000..5979d22 --- /dev/null +++ b/src/com/google/common/collect/GeneralRange.java @@ -0,0 +1,192 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.Ordering; +import com.google.common.collect.Range; +import java.io.Serializable; +import java.util.Comparator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class GeneralRange +implements Serializable { + private final Comparator comparator; + private final boolean hasLowerBound; + @Nullable + private final T lowerEndpoint; + private final BoundType lowerBoundType; + private final boolean hasUpperBound; + @Nullable + private final T upperEndpoint; + private final BoundType upperBoundType; + private transient GeneralRange reverse; + + static GeneralRange from(Range range) { + T lowerEndpoint = range.hasLowerBound() ? (T)range.lowerEndpoint() : null; + BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.OPEN; + T upperEndpoint = range.hasUpperBound() ? (T)range.upperEndpoint() : null; + BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.OPEN; + return new GeneralRange(Ordering.natural(), range.hasLowerBound(), lowerEndpoint, lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType); + } + + static GeneralRange all(Comparator comparator) { + return new GeneralRange(comparator, false, null, BoundType.OPEN, false, null, BoundType.OPEN); + } + + static GeneralRange downTo(Comparator comparator, @Nullable T endpoint, BoundType boundType) { + return new GeneralRange((Comparator)comparator, true, endpoint, boundType, false, null, BoundType.OPEN); + } + + static GeneralRange upTo(Comparator comparator, @Nullable T endpoint, BoundType boundType) { + return new GeneralRange((Comparator)comparator, false, null, BoundType.OPEN, true, endpoint, boundType); + } + + static GeneralRange range(Comparator comparator, @Nullable T lower, BoundType lowerType, @Nullable T upper, BoundType upperType) { + return new GeneralRange(comparator, true, lower, lowerType, true, upper, upperType); + } + + private GeneralRange(Comparator comparator, boolean hasLowerBound, @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound, @Nullable T upperEndpoint, BoundType upperBoundType) { + this.comparator = Preconditions.checkNotNull(comparator); + this.hasLowerBound = hasLowerBound; + this.hasUpperBound = hasUpperBound; + this.lowerEndpoint = lowerEndpoint; + this.lowerBoundType = Preconditions.checkNotNull(lowerBoundType); + this.upperEndpoint = upperEndpoint; + this.upperBoundType = Preconditions.checkNotNull(upperBoundType); + if (hasLowerBound) { + comparator.compare(lowerEndpoint, lowerEndpoint); + } + if (hasUpperBound) { + comparator.compare(upperEndpoint, upperEndpoint); + } + if (hasLowerBound && hasUpperBound) { + int cmp = comparator.compare(lowerEndpoint, upperEndpoint); + Preconditions.checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint, upperEndpoint); + if (cmp == 0) { + Preconditions.checkArgument(lowerBoundType != BoundType.OPEN | upperBoundType != BoundType.OPEN); + } + } + } + + Comparator comparator() { + return this.comparator; + } + + boolean hasLowerBound() { + return this.hasLowerBound; + } + + boolean hasUpperBound() { + return this.hasUpperBound; + } + + boolean isEmpty() { + return this.hasUpperBound() && this.tooLow(this.getUpperEndpoint()) || this.hasLowerBound() && this.tooHigh(this.getLowerEndpoint()); + } + + boolean tooLow(@Nullable T t) { + if (!this.hasLowerBound()) { + return false; + } + T lbound = this.getLowerEndpoint(); + int cmp = this.comparator.compare(t, lbound); + return cmp < 0 | cmp == 0 & this.getLowerBoundType() == BoundType.OPEN; + } + + boolean tooHigh(@Nullable T t) { + if (!this.hasUpperBound()) { + return false; + } + T ubound = this.getUpperEndpoint(); + int cmp = this.comparator.compare(t, ubound); + return cmp > 0 | cmp == 0 & this.getUpperBoundType() == BoundType.OPEN; + } + + boolean contains(@Nullable T t) { + return !this.tooLow(t) && !this.tooHigh(t); + } + + GeneralRange intersect(GeneralRange other) { + int cmp; + int cmp2; + Preconditions.checkNotNull(other); + Preconditions.checkArgument(this.comparator.equals(other.comparator)); + boolean hasLowBound = this.hasLowerBound; + T lowEnd = this.getLowerEndpoint(); + BoundType lowType = this.getLowerBoundType(); + if (!this.hasLowerBound()) { + hasLowBound = other.hasLowerBound; + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } else if (other.hasLowerBound() && ((cmp2 = this.comparator.compare(this.getLowerEndpoint(), other.getLowerEndpoint())) < 0 || cmp2 == 0 && other.getLowerBoundType() == BoundType.OPEN)) { + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } + boolean hasUpBound = this.hasUpperBound; + T upEnd = this.getUpperEndpoint(); + BoundType upType = this.getUpperBoundType(); + if (!this.hasUpperBound()) { + hasUpBound = other.hasUpperBound; + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } else if (other.hasUpperBound() && ((cmp = this.comparator.compare(this.getUpperEndpoint(), other.getUpperEndpoint())) > 0 || cmp == 0 && other.getUpperBoundType() == BoundType.OPEN)) { + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } + if (hasLowBound && hasUpBound && ((cmp = this.comparator.compare(lowEnd, upEnd)) > 0 || cmp == 0 && lowType == BoundType.OPEN && upType == BoundType.OPEN)) { + lowEnd = upEnd; + lowType = BoundType.OPEN; + upType = BoundType.CLOSED; + } + return new GeneralRange(this.comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof GeneralRange) { + GeneralRange r = (GeneralRange)obj; + return this.comparator.equals(r.comparator) && this.hasLowerBound == r.hasLowerBound && this.hasUpperBound == r.hasUpperBound && this.getLowerBoundType().equals((Object)r.getLowerBoundType()) && this.getUpperBoundType().equals((Object)r.getUpperBoundType()) && Objects.equal(this.getLowerEndpoint(), r.getLowerEndpoint()) && Objects.equal(this.getUpperEndpoint(), r.getUpperEndpoint()); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[]{this.comparator, this.getLowerEndpoint(), this.getLowerBoundType(), this.getUpperEndpoint(), this.getUpperBoundType()}); + } + + GeneralRange reverse() { + GeneralRange result = this.reverse; + if (result == null) { + result = new GeneralRange(Ordering.from(this.comparator).reverse(), this.hasUpperBound, this.getUpperEndpoint(), this.getUpperBoundType(), this.hasLowerBound, this.getLowerEndpoint(), this.getLowerBoundType()); + result.reverse = this; + this.reverse = result; + return this.reverse; + } + return result; + } + + public String toString() { + return this.comparator + ":" + (this.lowerBoundType == BoundType.CLOSED ? (char)'[' : '(') + (this.hasLowerBound ? this.lowerEndpoint : "-\u221e") + ',' + (this.hasUpperBound ? this.upperEndpoint : "\u221e") + (this.upperBoundType == BoundType.CLOSED ? (char)']' : ')'); + } + + T getLowerEndpoint() { + return this.lowerEndpoint; + } + + BoundType getLowerBoundType() { + return this.lowerBoundType; + } + + T getUpperEndpoint() { + return this.upperEndpoint; + } + + BoundType getUpperBoundType() { + return this.upperBoundType; + } +} diff --git a/src/com/google/common/collect/GenericMapMaker.java b/src/com/google/common/collect/GenericMapMaker.java new file mode 100644 index 0000000..7c851bc --- /dev/null +++ b/src/com/google/common/collect/GenericMapMaker.java @@ -0,0 +1,74 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.MapMaker; +import com.google.common.collect.MapMakerInternalMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +@Deprecated +@Beta +@GwtCompatible(emulated=true) +abstract class GenericMapMaker { + @GwtIncompatible(value="To be supported") + MapMaker.RemovalListener removalListener; + + GenericMapMaker() { + } + + @GwtIncompatible(value="To be supported") + abstract GenericMapMaker keyEquivalence(Equivalence var1); + + public abstract GenericMapMaker initialCapacity(int var1); + + abstract GenericMapMaker maximumSize(int var1); + + public abstract GenericMapMaker concurrencyLevel(int var1); + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public abstract GenericMapMaker weakKeys(); + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public abstract GenericMapMaker weakValues(); + + @Deprecated + @GwtIncompatible(value="java.lang.ref.SoftReference") + public abstract GenericMapMaker softValues(); + + abstract GenericMapMaker expireAfterWrite(long var1, TimeUnit var3); + + @GwtIncompatible(value="To be supported") + abstract GenericMapMaker expireAfterAccess(long var1, TimeUnit var3); + + @GwtIncompatible(value="To be supported") + MapMaker.RemovalListener getRemovalListener() { + return MoreObjects.firstNonNull(this.removalListener, NullListener.INSTANCE); + } + + public abstract ConcurrentMap makeMap(); + + @GwtIncompatible(value="MapMakerInternalMap") + abstract MapMakerInternalMap makeCustomMap(); + + @Deprecated + abstract ConcurrentMap makeComputingMap(Function var1); + + @GwtIncompatible(value="To be supported") + static enum NullListener implements MapMaker.RemovalListener + { + INSTANCE; + + + @Override + public void onRemoval(MapMaker.RemovalNotification notification) { + } + } +} diff --git a/src/com/google/common/collect/GwtTransient.java b/src/com/google/common/collect/GwtTransient.java new file mode 100644 index 0000000..74690d4 --- /dev/null +++ b/src/com/google/common/collect/GwtTransient.java @@ -0,0 +1,18 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.FIELD}) +@GwtCompatible +@interface GwtTransient { +} diff --git a/src/com/google/common/collect/HashBasedTable.java b/src/com/google/common/collect/HashBasedTable.java new file mode 100644 index 0000000..bf0f85d --- /dev/null +++ b/src/com/google/common/collect/HashBasedTable.java @@ -0,0 +1,92 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Supplier; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.StandardTable; +import com.google.common.collect.Table; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +public class HashBasedTable +extends StandardTable { + private static final long serialVersionUID = 0L; + + public static HashBasedTable create() { + return new HashBasedTable(new HashMap(), new Factory(0)); + } + + public static HashBasedTable create(int expectedRows, int expectedCellsPerRow) { + CollectPreconditions.checkNonnegative(expectedCellsPerRow, "expectedCellsPerRow"); + HashMap backingMap = Maps.newHashMapWithExpectedSize(expectedRows); + return new HashBasedTable(backingMap, new Factory(expectedCellsPerRow)); + } + + public static HashBasedTable create(Table table) { + HashBasedTable result = HashBasedTable.create(); + result.putAll((Table)table); + return result; + } + + HashBasedTable(Map> backingMap, Factory factory) { + super(backingMap, factory); + } + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + return super.contains(rowKey, columnKey); + } + + @Override + public boolean containsColumn(@Nullable Object columnKey) { + return super.containsColumn(columnKey); + } + + @Override + public boolean containsRow(@Nullable Object rowKey) { + return super.containsRow(rowKey); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return super.containsValue(value); + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + return super.get(rowKey, columnKey); + } + + @Override + public boolean equals(@Nullable Object obj) { + return super.equals(obj); + } + + @Override + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) { + return super.remove(rowKey, columnKey); + } + + private static class Factory + implements Supplier>, + Serializable { + final int expectedSize; + private static final long serialVersionUID = 0L; + + Factory(int expectedSize) { + this.expectedSize = expectedSize; + } + + @Override + public Map get() { + return Maps.newHashMapWithExpectedSize(this.expectedSize); + } + } +} diff --git a/src/com/google/common/collect/HashBiMap.java b/src/com/google/common/collect/HashBiMap.java new file mode 100644 index 0000000..dca43c2 --- /dev/null +++ b/src/com/google/common/collect/HashBiMap.java @@ -0,0 +1,632 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.BiMap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableEntry; +import com.google.common.collect.Maps; +import com.google.common.collect.Serialization; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class HashBiMap +extends AbstractMap +implements BiMap, +Serializable { + private static final double LOAD_FACTOR = 1.0; + private transient BiEntry[] hashTableKToV; + private transient BiEntry[] hashTableVToK; + private transient int size; + private transient int mask; + private transient int modCount; + private transient BiMap inverse; + @GwtIncompatible(value="Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static HashBiMap create() { + return HashBiMap.create(16); + } + + public static HashBiMap create(int expectedSize) { + return new HashBiMap(expectedSize); + } + + public static HashBiMap create(Map map) { + HashBiMap bimap = HashBiMap.create(map.size()); + bimap.putAll(map); + return bimap; + } + + private HashBiMap(int expectedSize) { + this.init(expectedSize); + } + + private void init(int expectedSize) { + CollectPreconditions.checkNonnegative(expectedSize, "expectedSize"); + int tableSize = Hashing.closedTableSize(expectedSize, 1.0); + this.hashTableKToV = this.createTable(tableSize); + this.hashTableVToK = this.createTable(tableSize); + this.mask = tableSize - 1; + this.modCount = 0; + this.size = 0; + } + + private void delete(BiEntry entry) { + int keyBucket = entry.keyHash & this.mask; + BiEntry prevBucketEntry = null; + BiEntry bucketEntry = this.hashTableKToV[keyBucket]; + while (true) { + if (bucketEntry == entry) { + if (prevBucketEntry == null) { + this.hashTableKToV[keyBucket] = entry.nextInKToVBucket; + break; + } + prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket; + break; + } + prevBucketEntry = bucketEntry; + bucketEntry = bucketEntry.nextInKToVBucket; + } + int valueBucket = entry.valueHash & this.mask; + prevBucketEntry = null; + BiEntry bucketEntry2 = this.hashTableVToK[valueBucket]; + while (true) { + if (bucketEntry2 == entry) { + if (prevBucketEntry == null) { + this.hashTableVToK[valueBucket] = entry.nextInVToKBucket; + break; + } + prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket; + break; + } + prevBucketEntry = bucketEntry2; + bucketEntry2 = bucketEntry2.nextInVToKBucket; + } + --this.size; + ++this.modCount; + } + + private void insert(BiEntry entry) { + int keyBucket = entry.keyHash & this.mask; + entry.nextInKToVBucket = this.hashTableKToV[keyBucket]; + this.hashTableKToV[keyBucket] = entry; + int valueBucket = entry.valueHash & this.mask; + entry.nextInVToKBucket = this.hashTableVToK[valueBucket]; + this.hashTableVToK[valueBucket] = entry; + ++this.size; + ++this.modCount; + } + + private static int hash(@Nullable Object o) { + return Hashing.smear(o == null ? 0 : o.hashCode()); + } + + private BiEntry seekByKey(@Nullable Object key, int keyHash) { + BiEntry entry = this.hashTableKToV[keyHash & this.mask]; + while (entry != null) { + if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) { + return entry; + } + entry = entry.nextInKToVBucket; + } + return null; + } + + private BiEntry seekByValue(@Nullable Object value, int valueHash) { + BiEntry entry = this.hashTableVToK[valueHash & this.mask]; + while (entry != null) { + if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) { + return entry; + } + entry = entry.nextInVToKBucket; + } + return null; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.seekByKey(key, HashBiMap.hash(key)) != null; + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.seekByValue(value, HashBiMap.hash(value)) != null; + } + + @Override + @Nullable + public V get(@Nullable Object key) { + BiEntry entry = this.seekByKey(key, HashBiMap.hash(key)); + return (V)(entry == null ? null : entry.value); + } + + @Override + public V put(@Nullable K key, @Nullable V value) { + return this.put(key, value, false); + } + + @Override + public V forcePut(@Nullable K key, @Nullable V value) { + return this.put(key, value, true); + } + + private V put(@Nullable K key, @Nullable V value, boolean force) { + int keyHash = HashBiMap.hash(key); + int valueHash = HashBiMap.hash(value); + BiEntry oldEntryForKey = this.seekByKey(key, keyHash); + if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash && Objects.equal(value, oldEntryForKey.value)) { + return value; + } + BiEntry oldEntryForValue = this.seekByValue(value, valueHash); + if (oldEntryForValue != null) { + if (force) { + this.delete(oldEntryForValue); + } else { + String string = String.valueOf(String.valueOf(value)); + throw new IllegalArgumentException(new StringBuilder(23 + string.length()).append("value already present: ").append(string).toString()); + } + } + if (oldEntryForKey != null) { + this.delete(oldEntryForKey); + } + BiEntry newEntry = new BiEntry(key, keyHash, value, valueHash); + this.insert(newEntry); + this.rehashIfNecessary(); + return (V)(oldEntryForKey == null ? null : oldEntryForKey.value); + } + + @Nullable + private K putInverse(@Nullable V value, @Nullable K key, boolean force) { + int valueHash = HashBiMap.hash(value); + int keyHash = HashBiMap.hash(key); + BiEntry oldEntryForValue = this.seekByValue(value, valueHash); + if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash && Objects.equal(key, oldEntryForValue.key)) { + return key; + } + BiEntry oldEntryForKey = this.seekByKey(key, keyHash); + if (oldEntryForKey != null) { + if (force) { + this.delete(oldEntryForKey); + } else { + String string = String.valueOf(String.valueOf(key)); + throw new IllegalArgumentException(new StringBuilder(23 + string.length()).append("value already present: ").append(string).toString()); + } + } + if (oldEntryForValue != null) { + this.delete(oldEntryForValue); + } + BiEntry newEntry = new BiEntry(key, keyHash, value, valueHash); + this.insert(newEntry); + this.rehashIfNecessary(); + return (K)(oldEntryForValue == null ? null : oldEntryForValue.key); + } + + private void rehashIfNecessary() { + BiEntry[] oldKToV = this.hashTableKToV; + if (Hashing.needsResizing(this.size, oldKToV.length, 1.0)) { + int newTableSize = oldKToV.length * 2; + this.hashTableKToV = this.createTable(newTableSize); + this.hashTableVToK = this.createTable(newTableSize); + this.mask = newTableSize - 1; + this.size = 0; + for (int bucket = 0; bucket < oldKToV.length; ++bucket) { + BiEntry entry = oldKToV[bucket]; + while (entry != null) { + BiEntry nextEntry = entry.nextInKToVBucket; + this.insert(entry); + entry = nextEntry; + } + } + ++this.modCount; + } + } + + private BiEntry[] createTable(int length) { + return new BiEntry[length]; + } + + @Override + public V remove(@Nullable Object key) { + BiEntry entry = this.seekByKey(key, HashBiMap.hash(key)); + if (entry == null) { + return null; + } + this.delete(entry); + return (V)entry.value; + } + + @Override + public void clear() { + this.size = 0; + Arrays.fill(this.hashTableKToV, null); + Arrays.fill(this.hashTableVToK, null); + ++this.modCount; + } + + @Override + public int size() { + return this.size; + } + + @Override + public Set keySet() { + return new KeySet(); + } + + @Override + public Set values() { + return this.inverse().keySet(); + } + + @Override + public Set> entrySet() { + return new EntrySet(); + } + + @Override + public BiMap inverse() { + return this.inverse == null ? (this.inverse = new Inverse()) : this.inverse; + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + Serialization.writeMap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + int size = Serialization.readCount(stream); + this.init(size); + Serialization.populateMap(this, stream, size); + } + + private static final class InverseSerializedForm + implements Serializable { + private final HashBiMap bimap; + + InverseSerializedForm(HashBiMap bimap) { + this.bimap = bimap; + } + + Object readResolve() { + return this.bimap.inverse(); + } + } + + private final class Inverse + extends AbstractMap + implements BiMap, + Serializable { + private Inverse() { + } + + BiMap forward() { + return HashBiMap.this; + } + + @Override + public int size() { + return HashBiMap.this.size; + } + + @Override + public void clear() { + this.forward().clear(); + } + + @Override + public boolean containsKey(@Nullable Object value) { + return this.forward().containsValue(value); + } + + @Override + public K get(@Nullable Object value) { + BiEntry entry = HashBiMap.this.seekByValue(value, HashBiMap.hash(value)); + return entry == null ? null : entry.key; + } + + @Override + public K put(@Nullable V value, @Nullable K key) { + return HashBiMap.this.putInverse(value, key, false); + } + + @Override + public K forcePut(@Nullable V value, @Nullable K key) { + return HashBiMap.this.putInverse(value, key, true); + } + + @Override + public K remove(@Nullable Object value) { + BiEntry entry = HashBiMap.this.seekByValue(value, HashBiMap.hash(value)); + if (entry == null) { + return null; + } + HashBiMap.this.delete(entry); + return entry.key; + } + + @Override + public BiMap inverse() { + return this.forward(); + } + + @Override + public Set keySet() { + return new InverseKeySet(); + } + + @Override + public Set values() { + return this.forward().keySet(); + } + + @Override + public Set> entrySet() { + return new Maps.EntrySet(){ + + @Override + Map map() { + return Inverse.this; + } + + @Override + public Iterator> iterator() { + return new Itr>(){ + + @Override + Map.Entry output(BiEntry entry) { + return new InverseEntry(entry); + } + + class InverseEntry + extends AbstractMapEntry { + BiEntry delegate; + + InverseEntry(BiEntry entry) { + this.delegate = entry; + } + + @Override + public V getKey() { + return this.delegate.value; + } + + @Override + public K getValue() { + return this.delegate.key; + } + + @Override + public K setValue(K key) { + Object oldKey = this.delegate.key; + int keyHash = HashBiMap.hash(key); + if (keyHash == this.delegate.keyHash && Objects.equal(key, oldKey)) { + return key; + } + Preconditions.checkArgument(HashBiMap.this.seekByKey(key, keyHash) == null, "value already present: %s", key); + HashBiMap.this.delete(this.delegate); + BiEntry newEntry = new BiEntry(key, keyHash, this.delegate.value, this.delegate.valueHash); + HashBiMap.this.insert(newEntry); + expectedModCount = HashBiMap.this.modCount; + return oldKey; + } + } + }; + } + }; + } + + Object writeReplace() { + return new InverseSerializedForm(HashBiMap.this); + } + + private final class InverseKeySet + extends Maps.KeySet { + InverseKeySet() { + super(Inverse.this); + } + + @Override + public boolean remove(@Nullable Object o) { + BiEntry entry = HashBiMap.this.seekByValue(o, HashBiMap.hash(o)); + if (entry == null) { + return false; + } + HashBiMap.this.delete(entry); + return true; + } + + @Override + public Iterator iterator() { + return new Itr(){ + + @Override + V output(BiEntry entry) { + return entry.value; + } + }; + } + } + } + + private final class EntrySet + extends Maps.EntrySet { + private EntrySet() { + } + + @Override + Map map() { + return HashBiMap.this; + } + + @Override + public Iterator> iterator() { + return new Itr>(){ + + @Override + Map.Entry output(BiEntry entry) { + return new MapEntry(entry); + } + + class MapEntry + extends AbstractMapEntry { + BiEntry delegate; + + MapEntry(BiEntry entry) { + this.delegate = entry; + } + + @Override + public K getKey() { + return this.delegate.key; + } + + @Override + public V getValue() { + return this.delegate.value; + } + + @Override + public V setValue(V value) { + Object oldValue = this.delegate.value; + int valueHash = HashBiMap.hash(value); + if (valueHash == this.delegate.valueHash && Objects.equal(value, oldValue)) { + return value; + } + Preconditions.checkArgument(HashBiMap.this.seekByValue(value, valueHash) == null, "value already present: %s", value); + HashBiMap.this.delete(this.delegate); + BiEntry newEntry = new BiEntry(this.delegate.key, this.delegate.keyHash, value, valueHash); + HashBiMap.this.insert(newEntry); + expectedModCount = HashBiMap.this.modCount; + if (toRemove == this.delegate) { + toRemove = newEntry; + } + this.delegate = newEntry; + return oldValue; + } + } + }; + } + } + + private final class KeySet + extends Maps.KeySet { + KeySet() { + super(HashBiMap.this); + } + + @Override + public Iterator iterator() { + return new Itr(){ + + @Override + K output(BiEntry entry) { + return entry.key; + } + }; + } + + @Override + public boolean remove(@Nullable Object o) { + BiEntry entry = HashBiMap.this.seekByKey(o, HashBiMap.hash(o)); + if (entry == null) { + return false; + } + HashBiMap.this.delete(entry); + return true; + } + } + + abstract class Itr + implements Iterator { + int nextBucket = 0; + BiEntry next = null; + BiEntry toRemove = null; + int expectedModCount = HashBiMap.access$000(HashBiMap.this); + + Itr() { + } + + private void checkForConcurrentModification() { + if (HashBiMap.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + @Override + public boolean hasNext() { + this.checkForConcurrentModification(); + if (this.next != null) { + return true; + } + while (this.nextBucket < HashBiMap.this.hashTableKToV.length) { + if (HashBiMap.this.hashTableKToV[this.nextBucket] != null) { + this.next = HashBiMap.this.hashTableKToV[this.nextBucket++]; + return true; + } + ++this.nextBucket; + } + return false; + } + + @Override + public T next() { + this.checkForConcurrentModification(); + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + BiEntry entry = this.next; + this.next = entry.nextInKToVBucket; + this.toRemove = entry; + return this.output(entry); + } + + @Override + public void remove() { + this.checkForConcurrentModification(); + CollectPreconditions.checkRemove(this.toRemove != null); + HashBiMap.this.delete(this.toRemove); + this.expectedModCount = HashBiMap.this.modCount; + this.toRemove = null; + } + + abstract T output(BiEntry var1); + } + + private static final class BiEntry + extends ImmutableEntry { + final int keyHash; + final int valueHash; + @Nullable + BiEntry nextInKToVBucket; + @Nullable + BiEntry nextInVToKBucket; + + BiEntry(K key, int keyHash, V value, int valueHash) { + super(key, value); + this.keyHash = keyHash; + this.valueHash = valueHash; + } + } +} diff --git a/src/com/google/common/collect/HashMultimap.java b/src/com/google/common/collect/HashMultimap.java new file mode 100644 index 0000000..fd8837c --- /dev/null +++ b/src/com/google/common/collect/HashMultimap.java @@ -0,0 +1,78 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractSetMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Serialization; +import com.google.common.collect.Sets; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Set; + +@GwtCompatible(serializable=true, emulated=true) +public final class HashMultimap +extends AbstractSetMultimap { + private static final int DEFAULT_VALUES_PER_KEY = 2; + @VisibleForTesting + transient int expectedValuesPerKey = 2; + @GwtIncompatible(value="Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static HashMultimap create() { + return new HashMultimap(); + } + + public static HashMultimap create(int expectedKeys, int expectedValuesPerKey) { + return new HashMultimap(expectedKeys, expectedValuesPerKey); + } + + public static HashMultimap create(Multimap multimap) { + return new HashMultimap(multimap); + } + + private HashMultimap() { + super(new HashMap()); + } + + private HashMultimap(int expectedKeys, int expectedValuesPerKey) { + super(Maps.newHashMapWithExpectedSize(expectedKeys)); + Preconditions.checkArgument(expectedValuesPerKey >= 0); + this.expectedValuesPerKey = expectedValuesPerKey; + } + + private HashMultimap(Multimap multimap) { + super(Maps.newHashMapWithExpectedSize(multimap.keySet().size())); + this.putAll(multimap); + } + + @Override + Set createCollection() { + return Sets.newHashSetWithExpectedSize(this.expectedValuesPerKey); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeInt(this.expectedValuesPerKey); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.expectedValuesPerKey = stream.readInt(); + int distinctKeys = Serialization.readCount(stream); + HashMap map = Maps.newHashMapWithExpectedSize(distinctKeys); + this.setMap(map); + Serialization.populateMultimap(this, stream, distinctKeys); + } +} diff --git a/src/com/google/common/collect/HashMultiset.java b/src/com/google/common/collect/HashMultiset.java new file mode 100644 index 0000000..cc2b172 --- /dev/null +++ b/src/com/google/common/collect/HashMultiset.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.AbstractMapBasedMultiset; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.Multisets; +import com.google.common.collect.Serialization; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; + +@GwtCompatible(serializable=true, emulated=true) +public final class HashMultiset +extends AbstractMapBasedMultiset { + @GwtIncompatible(value="Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static HashMultiset create() { + return new HashMultiset(); + } + + public static HashMultiset create(int distinctElements) { + return new HashMultiset(distinctElements); + } + + public static HashMultiset create(Iterable elements) { + HashMultiset multiset = HashMultiset.create(Multisets.inferDistinctElements(elements)); + Iterables.addAll(multiset, elements); + return multiset; + } + + private HashMultiset() { + super(new HashMap()); + } + + private HashMultiset(int distinctElements) { + super(Maps.newHashMapWithExpectedSize(distinctElements)); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + int distinctElements = Serialization.readCount(stream); + this.setBackingMap(Maps.newHashMapWithExpectedSize(distinctElements)); + Serialization.populateMultiset(this, stream, distinctElements); + } +} diff --git a/src/com/google/common/collect/Hashing.java b/src/com/google/common/collect/Hashing.java new file mode 100644 index 0000000..295116c --- /dev/null +++ b/src/com/google/common/collect/Hashing.java @@ -0,0 +1,37 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +final class Hashing { + private static final int C1 = -862048943; + private static final int C2 = 461845907; + private static int MAX_TABLE_SIZE = 0x40000000; + + private Hashing() { + } + + static int smear(int hashCode) { + return 461845907 * Integer.rotateLeft(hashCode * -862048943, 15); + } + + static int smearedHash(@Nullable Object o) { + return Hashing.smear(o == null ? 0 : o.hashCode()); + } + + static int closedTableSize(int expectedEntries, double loadFactor) { + int tableSize; + if ((expectedEntries = Math.max(expectedEntries, 2)) > (int)(loadFactor * (double)(tableSize = Integer.highestOneBit(expectedEntries)))) { + return (tableSize <<= 1) > 0 ? tableSize : MAX_TABLE_SIZE; + } + return tableSize; + } + + static boolean needsResizing(int size, int tableSize, double loadFactor) { + return (double)size > loadFactor * (double)tableSize && tableSize < MAX_TABLE_SIZE; + } +} diff --git a/src/com/google/common/collect/ImmutableAsList.java b/src/com/google/common/collect/ImmutableAsList.java new file mode 100644 index 0000000..0c56c45 --- /dev/null +++ b/src/com/google/common/collect/ImmutableAsList.java @@ -0,0 +1,67 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; + +@GwtCompatible(serializable=true, emulated=true) +abstract class ImmutableAsList +extends ImmutableList { + ImmutableAsList() { + } + + abstract ImmutableCollection delegateCollection(); + + @Override + public boolean contains(Object target) { + return this.delegateCollection().contains(target); + } + + @Override + public int size() { + return this.delegateCollection().size(); + } + + @Override + public boolean isEmpty() { + return this.delegateCollection().isEmpty(); + } + + @Override + boolean isPartialView() { + return this.delegateCollection().isPartialView(); + } + + @GwtIncompatible(value="serialization") + private void readObject(ObjectInputStream stream) throws InvalidObjectException { + throw new InvalidObjectException("Use SerializedForm"); + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new SerializedForm(this.delegateCollection()); + } + + @GwtIncompatible(value="serialization") + static class SerializedForm + implements Serializable { + final ImmutableCollection collection; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableCollection collection) { + this.collection = collection; + } + + Object readResolve() { + return this.collection.asList(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableBiMap.java b/src/com/google/common/collect/ImmutableBiMap.java new file mode 100644 index 0000000..7be68a2 --- /dev/null +++ b/src/com/google/common/collect/ImmutableBiMap.java @@ -0,0 +1,131 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.BiMap; +import com.google.common.collect.EmptyImmutableBiMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.RegularImmutableBiMap; +import com.google.common.collect.SingletonImmutableBiMap; +import java.util.Map; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableBiMap +extends ImmutableMap +implements BiMap { + private static final Map.Entry[] EMPTY_ENTRY_ARRAY = new Map.Entry[0]; + + public static ImmutableBiMap of() { + return EmptyImmutableBiMap.INSTANCE; + } + + public static ImmutableBiMap of(K k1, V v1) { + return new SingletonImmutableBiMap(k1, v1); + } + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2) { + return new RegularImmutableBiMap(ImmutableBiMap.entryOf(k1, v1), ImmutableBiMap.entryOf(k2, v2)); + } + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3) { + return new RegularImmutableBiMap(ImmutableBiMap.entryOf(k1, v1), ImmutableBiMap.entryOf(k2, v2), ImmutableBiMap.entryOf(k3, v3)); + } + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return new RegularImmutableBiMap(ImmutableBiMap.entryOf(k1, v1), ImmutableBiMap.entryOf(k2, v2), ImmutableBiMap.entryOf(k3, v3), ImmutableBiMap.entryOf(k4, v4)); + } + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return new RegularImmutableBiMap(ImmutableBiMap.entryOf(k1, v1), ImmutableBiMap.entryOf(k2, v2), ImmutableBiMap.entryOf(k3, v3), ImmutableBiMap.entryOf(k4, v4), ImmutableBiMap.entryOf(k5, v5)); + } + + public static Builder builder() { + return new Builder(); + } + + public static ImmutableBiMap copyOf(Map map) { + ImmutableBiMap bimap; + if (map instanceof ImmutableBiMap && !(bimap = (ImmutableBiMap)map).isPartialView()) { + return bimap; + } + Map.Entry[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY); + switch (entries.length) { + case 0: { + return ImmutableBiMap.of(); + } + case 1: { + Map.Entry entry = entries[0]; + return ImmutableBiMap.of(entry.getKey(), entry.getValue()); + } + } + return new RegularImmutableBiMap(entries); + } + + ImmutableBiMap() { + } + + @Override + public abstract ImmutableBiMap inverse(); + + @Override + public ImmutableSet values() { + return ((ImmutableMap)((Object)this.inverse())).keySet(); + } + + @Override + @Deprecated + public V forcePut(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + Object writeReplace() { + return new SerializedForm(this); + } + + private static class SerializedForm + extends ImmutableMap.SerializedForm { + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableBiMap bimap) { + super(bimap); + } + + @Override + Object readResolve() { + Builder builder = new Builder(); + return this.createMap(builder); + } + } + + public static final class Builder + extends ImmutableMap.Builder { + @Override + public Builder put(K key, V value) { + super.put(key, value); + return this; + } + + @Override + public Builder putAll(Map map) { + super.putAll(map); + return this; + } + + @Override + public ImmutableBiMap build() { + switch (this.size) { + case 0: { + return ImmutableBiMap.of(); + } + case 1: { + return ImmutableBiMap.of(this.entries[0].getKey(), this.entries[0].getValue()); + } + } + return new RegularImmutableBiMap(this.size, this.entries); + } + } +} diff --git a/src/com/google/common/collect/ImmutableClassToInstanceMap.java b/src/com/google/common/collect/ImmutableClassToInstanceMap.java new file mode 100644 index 0000000..6470b01 --- /dev/null +++ b/src/com/google/common/collect/ImmutableClassToInstanceMap.java @@ -0,0 +1,79 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ClassToInstanceMap; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.primitives.Primitives; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +public final class ImmutableClassToInstanceMap +extends ForwardingMap, B> +implements ClassToInstanceMap, +Serializable { + private final ImmutableMap, B> delegate; + + public static Builder builder() { + return new Builder(); + } + + public static ImmutableClassToInstanceMap copyOf(Map, ? extends S> map) { + if (map instanceof ImmutableClassToInstanceMap) { + ImmutableClassToInstanceMap cast = (ImmutableClassToInstanceMap)map; + return cast; + } + return new Builder().putAll(map).build(); + } + + private ImmutableClassToInstanceMap(ImmutableMap, B> delegate) { + this.delegate = delegate; + } + + @Override + protected Map, B> delegate() { + return this.delegate; + } + + @Override + @Nullable + public T getInstance(Class type) { + return (T)this.delegate.get(Preconditions.checkNotNull(type)); + } + + @Override + @Deprecated + public T putInstance(Class type, T value) { + throw new UnsupportedOperationException(); + } + + public static final class Builder { + private final ImmutableMap.Builder, B> mapBuilder = ImmutableMap.builder(); + + public Builder put(Class key, T value) { + this.mapBuilder.put(key, value); + return this; + } + + public Builder putAll(Map, ? extends T> map) { + for (Map.Entry, T> entry : map.entrySet()) { + Class type = entry.getKey(); + T value = entry.getValue(); + this.mapBuilder.put(type, Builder.cast(type, value)); + } + return this; + } + + private static T cast(Class type, B value) { + return Primitives.wrap(type).cast(value); + } + + public ImmutableClassToInstanceMap build() { + return new ImmutableClassToInstanceMap(this.mapBuilder.build()); + } + } +} diff --git a/src/com/google/common/collect/ImmutableCollection.java b/src/com/google/common/collect/ImmutableCollection.java new file mode 100644 index 0000000..08fe9ab --- /dev/null +++ b/src/com/google/common/collect/ImmutableCollection.java @@ -0,0 +1,216 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.RegularImmutableAsList; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public abstract class ImmutableCollection +extends AbstractCollection +implements Serializable { + private transient ImmutableList asList; + + ImmutableCollection() { + } + + @Override + public abstract UnmodifiableIterator iterator(); + + @Override + public final Object[] toArray() { + int size = this.size(); + if (size == 0) { + return ObjectArrays.EMPTY_ARRAY; + } + Object[] result = new Object[size]; + this.copyIntoArray(result, 0); + return result; + } + + @Override + public final T[] toArray(T[] other) { + Preconditions.checkNotNull(other); + int size = this.size(); + if (other.length < size) { + other = ObjectArrays.newArray(other, size); + } else if (other.length > size) { + other[size] = null; + } + this.copyIntoArray(other, 0); + return other; + } + + @Override + public boolean contains(@Nullable Object object) { + return object != null && super.contains(object); + } + + @Override + @Deprecated + public final boolean add(E e) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final boolean remove(Object object) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final boolean addAll(Collection newElements) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final boolean removeAll(Collection oldElements) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final boolean retainAll(Collection elementsToKeep) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void clear() { + throw new UnsupportedOperationException(); + } + + public ImmutableList asList() { + ImmutableList list = this.asList; + return list == null ? (this.asList = this.createAsList()) : list; + } + + ImmutableList createAsList() { + switch (this.size()) { + case 0: { + return ImmutableList.of(); + } + case 1: { + return ImmutableList.of(this.iterator().next()); + } + } + return new RegularImmutableAsList(this, this.toArray()); + } + + abstract boolean isPartialView(); + + int copyIntoArray(Object[] dst, int offset) { + for (Object e : this) { + dst[offset++] = e; + } + return offset; + } + + Object writeReplace() { + return new ImmutableList.SerializedForm(this.toArray()); + } + + static abstract class ArrayBasedBuilder + extends Builder { + Object[] contents; + int size; + + ArrayBasedBuilder(int initialCapacity) { + CollectPreconditions.checkNonnegative(initialCapacity, "initialCapacity"); + this.contents = new Object[initialCapacity]; + this.size = 0; + } + + private void ensureCapacity(int minCapacity) { + if (this.contents.length < minCapacity) { + this.contents = ObjectArrays.arraysCopyOf(this.contents, ArrayBasedBuilder.expandedCapacity(this.contents.length, minCapacity)); + } + } + + @Override + public ArrayBasedBuilder add(E element) { + Preconditions.checkNotNull(element); + this.ensureCapacity(this.size + 1); + this.contents[this.size++] = element; + return this; + } + + @Override + public Builder add(E ... elements) { + ObjectArrays.checkElementsNotNull((Object[])elements); + this.ensureCapacity(this.size + elements.length); + System.arraycopy(elements, 0, this.contents, this.size, elements.length); + this.size += elements.length; + return this; + } + + @Override + public Builder addAll(Iterable elements) { + if (elements instanceof Collection) { + Collection collection = (Collection)elements; + this.ensureCapacity(this.size + collection.size()); + } + super.addAll(elements); + return this; + } + } + + public static abstract class Builder { + static final int DEFAULT_INITIAL_CAPACITY = 4; + + static int expandedCapacity(int oldCapacity, int minCapacity) { + if (minCapacity < 0) { + throw new AssertionError((Object)"cannot store more than MAX_VALUE elements"); + } + int newCapacity = oldCapacity + (oldCapacity >> 1) + 1; + if (newCapacity < minCapacity) { + newCapacity = Integer.highestOneBit(minCapacity - 1) << 1; + } + if (newCapacity < 0) { + newCapacity = Integer.MAX_VALUE; + } + return newCapacity; + } + + Builder() { + } + + public abstract Builder add(E var1); + + public Builder add(E ... elements) { + for (E element : elements) { + this.add(element); + } + return this; + } + + public Builder addAll(Iterable elements) { + for (E element : elements) { + this.add(element); + } + return this; + } + + public Builder addAll(Iterator elements) { + while (elements.hasNext()) { + this.add(elements.next()); + } + return this; + } + + public abstract ImmutableCollection build(); + } +} diff --git a/src/com/google/common/collect/ImmutableEntry.java b/src/com/google/common/collect/ImmutableEntry.java new file mode 100644 index 0000000..6282bcf --- /dev/null +++ b/src/com/google/common/collect/ImmutableEntry.java @@ -0,0 +1,40 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractMapEntry; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +class ImmutableEntry +extends AbstractMapEntry +implements Serializable { + final K key; + final V value; + private static final long serialVersionUID = 0L; + + ImmutableEntry(@Nullable K key, @Nullable V value) { + this.key = key; + this.value = value; + } + + @Override + @Nullable + public final K getKey() { + return this.key; + } + + @Override + @Nullable + public final V getValue() { + return this.value; + } + + @Override + public final V setValue(V value) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/ImmutableEnumMap.java b/src/com/google/common/collect/ImmutableEnumMap.java new file mode 100644 index 0000000..438b262 --- /dev/null +++ b/src/com/google/common/collect/ImmutableEnumMap.java @@ -0,0 +1,140 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class ImmutableEnumMap, V> +extends ImmutableMap { + private final transient EnumMap delegate; + + static , V> ImmutableMap asImmutable(EnumMap map) { + switch (map.size()) { + case 0: { + return ImmutableMap.of(); + } + case 1: { + Map.Entry entry = Iterables.getOnlyElement(map.entrySet()); + return ImmutableMap.of(entry.getKey(), entry.getValue()); + } + } + return new ImmutableEnumMap(map); + } + + private ImmutableEnumMap(EnumMap delegate) { + this.delegate = delegate; + Preconditions.checkArgument(!delegate.isEmpty()); + } + + @Override + ImmutableSet createKeySet() { + return new ImmutableSet(){ + + @Override + public boolean contains(Object object) { + return ImmutableEnumMap.this.delegate.containsKey(object); + } + + @Override + public int size() { + return ImmutableEnumMap.this.size(); + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.unmodifiableIterator(ImmutableEnumMap.this.delegate.keySet().iterator()); + } + + @Override + boolean isPartialView() { + return true; + } + }; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.delegate.containsKey(key); + } + + @Override + public V get(Object key) { + return this.delegate.get(key); + } + + @Override + ImmutableSet> createEntrySet() { + return new ImmutableMapEntrySet(){ + + @Override + ImmutableMap map() { + return ImmutableEnumMap.this; + } + + @Override + public UnmodifiableIterator> iterator() { + return new UnmodifiableIterator>(){ + private final Iterator> backingIterator; + { + this.backingIterator = ImmutableEnumMap.this.delegate.entrySet().iterator(); + } + + @Override + public boolean hasNext() { + return this.backingIterator.hasNext(); + } + + @Override + public Map.Entry next() { + Map.Entry entry = this.backingIterator.next(); + return Maps.immutableEntry(entry.getKey(), entry.getValue()); + } + }; + } + }; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + Object writeReplace() { + return new EnumSerializedForm(this.delegate); + } + + private static class EnumSerializedForm, V> + implements Serializable { + final EnumMap delegate; + private static final long serialVersionUID = 0L; + + EnumSerializedForm(EnumMap delegate) { + this.delegate = delegate; + } + + Object readResolve() { + return new ImmutableEnumMap(this.delegate); + } + } +} diff --git a/src/com/google/common/collect/ImmutableEnumSet.java b/src/com/google/common/collect/ImmutableEnumSet.java new file mode 100644 index 0000000..953ac97 --- /dev/null +++ b/src/com/google/common/collect/ImmutableEnumSet.java @@ -0,0 +1,101 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Collection; +import java.util.EnumSet; + +@GwtCompatible(serializable=true, emulated=true) +final class ImmutableEnumSet> +extends ImmutableSet { + private final transient EnumSet delegate; + private transient int hashCode; + + static > ImmutableSet asImmutable(EnumSet set) { + switch (set.size()) { + case 0: { + return ImmutableSet.of(); + } + case 1: { + return ImmutableSet.of(Iterables.getOnlyElement(set)); + } + } + return new ImmutableEnumSet(set); + } + + private ImmutableEnumSet(EnumSet delegate) { + this.delegate = delegate; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.unmodifiableIterator(this.delegate.iterator()); + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean contains(Object object) { + return this.delegate.contains(object); + } + + @Override + public boolean containsAll(Collection collection) { + return this.delegate.containsAll(collection); + } + + @Override + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + @Override + public boolean equals(Object object) { + return object == this || this.delegate.equals(object); + } + + @Override + public int hashCode() { + int result = this.hashCode; + return result == 0 ? (this.hashCode = this.delegate.hashCode()) : result; + } + + @Override + public String toString() { + return this.delegate.toString(); + } + + @Override + Object writeReplace() { + return new EnumSerializedForm(this.delegate); + } + + private static class EnumSerializedForm> + implements Serializable { + final EnumSet delegate; + private static final long serialVersionUID = 0L; + + EnumSerializedForm(EnumSet delegate) { + this.delegate = delegate; + } + + Object readResolve() { + return new ImmutableEnumSet((EnumSet)this.delegate.clone()); + } + } +} diff --git a/src/com/google/common/collect/ImmutableList.java b/src/com/google/common/collect/ImmutableList.java new file mode 100644 index 0000000..147580b --- /dev/null +++ b/src/com/google/common/collect/ImmutableList.java @@ -0,0 +1,434 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIndexedListIterator; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.Lists; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.RegularImmutableList; +import com.google.common.collect.SingletonImmutableList; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.collect.UnmodifiableListIterator; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableList +extends ImmutableCollection +implements List, +RandomAccess { + private static final ImmutableList EMPTY = new RegularImmutableList(ObjectArrays.EMPTY_ARRAY); + + public static ImmutableList of() { + return EMPTY; + } + + public static ImmutableList of(E element) { + return new SingletonImmutableList(element); + } + + public static ImmutableList of(E e1, E e2) { + return ImmutableList.construct(e1, e2); + } + + public static ImmutableList of(E e1, E e2, E e3) { + return ImmutableList.construct(e1, e2, e3); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4) { + return ImmutableList.construct(e1, e2, e3, e4); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5) { + return ImmutableList.construct(e1, e2, e3, e4, e5); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6, e7); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6, e7, e8); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6, e7, e8, e9); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) { + return ImmutableList.construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11); + } + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E ... others) { + Object[] array = new Object[12 + others.length]; + array[0] = e1; + array[1] = e2; + array[2] = e3; + array[3] = e4; + array[4] = e5; + array[5] = e6; + array[6] = e7; + array[7] = e8; + array[8] = e9; + array[9] = e10; + array[10] = e11; + array[11] = e12; + System.arraycopy(others, 0, array, 12, others.length); + return ImmutableList.construct(array); + } + + public static ImmutableList copyOf(Iterable elements) { + Preconditions.checkNotNull(elements); + return elements instanceof Collection ? ImmutableList.copyOf((Collection)elements) : ImmutableList.copyOf(elements.iterator()); + } + + public static ImmutableList copyOf(Collection elements) { + if (elements instanceof ImmutableCollection) { + ImmutableList list = ((ImmutableCollection)elements).asList(); + return list.isPartialView() ? ImmutableList.asImmutableList(list.toArray()) : list; + } + return ImmutableList.construct(elements.toArray()); + } + + public static ImmutableList copyOf(Iterator elements) { + if (!elements.hasNext()) { + return ImmutableList.of(); + } + E first = elements.next(); + if (!elements.hasNext()) { + return ImmutableList.of(first); + } + return ((Builder)((Builder)new Builder().add((Object)first)).addAll(elements)).build(); + } + + public static ImmutableList copyOf(E[] elements) { + switch (elements.length) { + case 0: { + return ImmutableList.of(); + } + case 1: { + return new SingletonImmutableList(elements[0]); + } + } + return new RegularImmutableList(ObjectArrays.checkElementsNotNull((Object[])elements.clone())); + } + + private static ImmutableList construct(Object ... elements) { + return ImmutableList.asImmutableList(ObjectArrays.checkElementsNotNull(elements)); + } + + static ImmutableList asImmutableList(Object[] elements) { + return ImmutableList.asImmutableList(elements, elements.length); + } + + static ImmutableList asImmutableList(Object[] elements, int length) { + switch (length) { + case 0: { + return ImmutableList.of(); + } + case 1: { + SingletonImmutableList list = new SingletonImmutableList(elements[0]); + return list; + } + } + if (length < elements.length) { + elements = ObjectArrays.arraysCopyOf(elements, length); + } + return new RegularImmutableList(elements); + } + + ImmutableList() { + } + + @Override + public UnmodifiableIterator iterator() { + return this.listIterator(); + } + + @Override + public UnmodifiableListIterator listIterator() { + return this.listIterator(0); + } + + @Override + public UnmodifiableListIterator listIterator(int index) { + return new AbstractIndexedListIterator(this.size(), index){ + + @Override + protected E get(int index) { + return ImmutableList.this.get(index); + } + }; + } + + @Override + public int indexOf(@Nullable Object object) { + return object == null ? -1 : Lists.indexOfImpl(this, object); + } + + @Override + public int lastIndexOf(@Nullable Object object) { + return object == null ? -1 : Lists.lastIndexOfImpl(this, object); + } + + @Override + public boolean contains(@Nullable Object object) { + return this.indexOf(object) >= 0; + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size()); + int length = toIndex - fromIndex; + switch (length) { + case 0: { + return ImmutableList.of(); + } + case 1: { + return ImmutableList.of(this.get(fromIndex)); + } + } + return this.subListUnchecked(fromIndex, toIndex); + } + + ImmutableList subListUnchecked(int fromIndex, int toIndex) { + return new SubList(fromIndex, toIndex - fromIndex); + } + + @Override + @Deprecated + public final boolean addAll(int index, Collection newElements) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final E set(int index, E element) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void add(int index, E element) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final E remove(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public final ImmutableList asList() { + return this; + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + int size = this.size(); + for (int i = 0; i < size; ++i) { + dst[offset + i] = this.get(i); + } + return offset + size; + } + + public ImmutableList reverse() { + return new ReverseImmutableList(this); + } + + @Override + public boolean equals(@Nullable Object obj) { + return Lists.equalsImpl(this, obj); + } + + @Override + public int hashCode() { + int hashCode = 1; + int n = this.size(); + for (int i = 0; i < n; ++i) { + hashCode = 31 * hashCode + this.get(i).hashCode(); + hashCode = ~(~hashCode); + } + return hashCode; + } + + private void readObject(ObjectInputStream stream) throws InvalidObjectException { + throw new InvalidObjectException("Use SerializedForm"); + } + + @Override + Object writeReplace() { + return new SerializedForm(this.toArray()); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder + extends ImmutableCollection.ArrayBasedBuilder { + public Builder() { + this(4); + } + + Builder(int capacity) { + super(capacity); + } + + @Override + public Builder add(E element) { + super.add((Object)element); + return this; + } + + @Override + public Builder addAll(Iterable elements) { + super.addAll(elements); + return this; + } + + @Override + public Builder add(E ... elements) { + super.add(elements); + return this; + } + + @Override + public Builder addAll(Iterator elements) { + super.addAll(elements); + return this; + } + + @Override + public ImmutableList build() { + return ImmutableList.asImmutableList(this.contents, this.size); + } + } + + static class SerializedForm + implements Serializable { + final Object[] elements; + private static final long serialVersionUID = 0L; + + SerializedForm(Object[] elements) { + this.elements = elements; + } + + Object readResolve() { + return ImmutableList.copyOf(this.elements); + } + } + + private static class ReverseImmutableList + extends ImmutableList { + private final transient ImmutableList forwardList; + + ReverseImmutableList(ImmutableList backingList) { + this.forwardList = backingList; + } + + private int reverseIndex(int index) { + return this.size() - 1 - index; + } + + private int reversePosition(int index) { + return this.size() - index; + } + + @Override + public ImmutableList reverse() { + return this.forwardList; + } + + @Override + public boolean contains(@Nullable Object object) { + return this.forwardList.contains(object); + } + + @Override + public int indexOf(@Nullable Object object) { + int index = this.forwardList.lastIndexOf(object); + return index >= 0 ? this.reverseIndex(index) : -1; + } + + @Override + public int lastIndexOf(@Nullable Object object) { + int index = this.forwardList.indexOf(object); + return index >= 0 ? this.reverseIndex(index) : -1; + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size()); + return ((ImmutableList)this.forwardList.subList(this.reversePosition(toIndex), this.reversePosition(fromIndex))).reverse(); + } + + @Override + public E get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.forwardList.get(this.reverseIndex(index)); + } + + @Override + public int size() { + return this.forwardList.size(); + } + + @Override + boolean isPartialView() { + return this.forwardList.isPartialView(); + } + } + + class SubList + extends ImmutableList { + final transient int offset; + final transient int length; + + SubList(int offset, int length) { + this.offset = offset; + this.length = length; + } + + @Override + public int size() { + return this.length; + } + + @Override + public E get(int index) { + Preconditions.checkElementIndex(index, this.length); + return ImmutableList.this.get(index + this.offset); + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, this.length); + return ImmutableList.this.subList(fromIndex + this.offset, toIndex + this.offset); + } + + @Override + boolean isPartialView() { + return true; + } + } +} diff --git a/src/com/google/common/collect/ImmutableListMultimap.java b/src/com/google/common/collect/ImmutableListMultimap.java new file mode 100644 index 0000000..2b34af6 --- /dev/null +++ b/src/com/google/common/collect/ImmutableListMultimap.java @@ -0,0 +1,227 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.EmptyImmutableListMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Serialization; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public class ImmutableListMultimap +extends ImmutableMultimap +implements ListMultimap { + private transient ImmutableListMultimap inverse; + @GwtIncompatible(value="Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static ImmutableListMultimap of() { + return EmptyImmutableListMultimap.INSTANCE; + } + + public static ImmutableListMultimap of(K k1, V v1) { + Builder builder = ImmutableListMultimap.builder(); + builder.put((Object)k1, (Object)v1); + return builder.build(); + } + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2) { + Builder builder = ImmutableListMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + return builder.build(); + } + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) { + Builder builder = ImmutableListMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + return builder.build(); + } + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + Builder builder = ImmutableListMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + builder.put((Object)k4, (Object)v4); + return builder.build(); + } + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + Builder builder = ImmutableListMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + builder.put((Object)k4, (Object)v4); + builder.put((Object)k5, (Object)v5); + return builder.build(); + } + + public static Builder builder() { + return new Builder(); + } + + public static ImmutableListMultimap copyOf(Multimap multimap) { + ImmutableListMultimap kvMultimap; + if (multimap.isEmpty()) { + return ImmutableListMultimap.of(); + } + if (multimap instanceof ImmutableListMultimap && !(kvMultimap = (ImmutableListMultimap)multimap).isPartialView()) { + return kvMultimap; + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int size = 0; + for (Map.Entry> entry : multimap.asMap().entrySet()) { + ImmutableList list = ImmutableList.copyOf(entry.getValue()); + if (list.isEmpty()) continue; + builder.put(entry.getKey(), list); + size += list.size(); + } + return new ImmutableListMultimap(builder.build(), size); + } + + ImmutableListMultimap(ImmutableMap> map, int size) { + super(map, size); + } + + @Override + public ImmutableList get(@Nullable K key) { + ImmutableList list = (ImmutableList)this.map.get(key); + return list == null ? ImmutableList.of() : list; + } + + @Override + public ImmutableListMultimap inverse() { + ImmutableListMultimap result = this.inverse; + return result == null ? (this.inverse = this.invert()) : result; + } + + private ImmutableListMultimap invert() { + Builder builder = ImmutableListMultimap.builder(); + for (Map.Entry entry : this.entries()) { + builder.put(entry.getValue(), entry.getKey()); + } + ImmutableMultimap invertedMultimap = builder.build(); + ((ImmutableListMultimap)invertedMultimap).inverse = this; + return invertedMultimap; + } + + @Override + @Deprecated + public ImmutableList removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public ImmutableList replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + ImmutableMap tmpMap; + stream.defaultReadObject(); + int keyCount = stream.readInt(); + if (keyCount < 0) { + int n = keyCount; + throw new InvalidObjectException(new StringBuilder(29).append("Invalid key count ").append(n).toString()); + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int tmpSize = 0; + for (int i = 0; i < keyCount; ++i) { + Object key = stream.readObject(); + int valueCount = stream.readInt(); + if (valueCount <= 0) { + int n = valueCount; + throw new InvalidObjectException(new StringBuilder(31).append("Invalid value count ").append(n).toString()); + } + Object[] array = new Object[valueCount]; + for (int j = 0; j < valueCount; ++j) { + array[j] = stream.readObject(); + } + builder.put(key, ImmutableList.copyOf(array)); + tmpSize += valueCount; + } + try { + tmpMap = builder.build(); + } + catch (IllegalArgumentException e) { + throw (InvalidObjectException)new InvalidObjectException(e.getMessage()).initCause(e); + } + ImmutableMultimap.FieldSettersHolder.MAP_FIELD_SETTER.set((ImmutableMultimap)this, tmpMap); + ImmutableMultimap.FieldSettersHolder.SIZE_FIELD_SETTER.set((ImmutableMultimap)this, tmpSize); + } + + public static final class Builder + extends ImmutableMultimap.Builder { + @Override + public Builder put(K key, V value) { + super.put(key, value); + return this; + } + + @Override + public Builder put(Map.Entry entry) { + super.put(entry); + return this; + } + + @Override + public Builder putAll(K key, Iterable values) { + super.putAll(key, values); + return this; + } + + @Override + public Builder putAll(K key, V ... values) { + super.putAll(key, values); + return this; + } + + @Override + public Builder putAll(Multimap multimap) { + super.putAll(multimap); + return this; + } + + @Override + public Builder orderKeysBy(Comparator keyComparator) { + super.orderKeysBy(keyComparator); + return this; + } + + @Override + public Builder orderValuesBy(Comparator valueComparator) { + super.orderValuesBy(valueComparator); + return this; + } + + @Override + public ImmutableListMultimap build() { + return (ImmutableListMultimap)super.build(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMap.java b/src/com/google/common/collect/ImmutableMap.java new file mode 100644 index 0000000..d0df598 --- /dev/null +++ b/src/com/google/common/collect/ImmutableMap.java @@ -0,0 +1,371 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableEnumMap; +import com.google.common.collect.ImmutableMapEntry; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableMapKeySet; +import com.google.common.collect.ImmutableMapValues; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Maps; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.RegularImmutableMap; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableMap +implements Map, +Serializable { + private static final Map.Entry[] EMPTY_ENTRY_ARRAY = new Map.Entry[0]; + private transient ImmutableSet> entrySet; + private transient ImmutableSet keySet; + private transient ImmutableCollection values; + private transient ImmutableSetMultimap multimapView; + + public static ImmutableMap of() { + return ImmutableBiMap.of(); + } + + public static ImmutableMap of(K k1, V v1) { + return ImmutableBiMap.of(k1, v1); + } + + public static ImmutableMap of(K k1, V v1, K k2, V v2) { + return new RegularImmutableMap(ImmutableMap.entryOf(k1, v1), ImmutableMap.entryOf(k2, v2)); + } + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3) { + return new RegularImmutableMap(ImmutableMap.entryOf(k1, v1), ImmutableMap.entryOf(k2, v2), ImmutableMap.entryOf(k3, v3)); + } + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return new RegularImmutableMap(ImmutableMap.entryOf(k1, v1), ImmutableMap.entryOf(k2, v2), ImmutableMap.entryOf(k3, v3), ImmutableMap.entryOf(k4, v4)); + } + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return new RegularImmutableMap(ImmutableMap.entryOf(k1, v1), ImmutableMap.entryOf(k2, v2), ImmutableMap.entryOf(k3, v3), ImmutableMap.entryOf(k4, v4), ImmutableMap.entryOf(k5, v5)); + } + + static ImmutableMapEntry.TerminalEntry entryOf(K key, V value) { + CollectPreconditions.checkEntryNotNull(key, value); + return new ImmutableMapEntry.TerminalEntry(key, value); + } + + public static Builder builder() { + return new Builder(); + } + + static void checkNoConflict(boolean safe, String conflictDescription, Map.Entry entry1, Map.Entry entry2) { + if (!safe) { + String string = String.valueOf(String.valueOf(conflictDescription)); + String string2 = String.valueOf(String.valueOf(entry1)); + String string3 = String.valueOf(String.valueOf(entry2)); + throw new IllegalArgumentException(new StringBuilder(34 + string.length() + string2.length() + string3.length()).append("Multiple entries with same ").append(string).append(": ").append(string2).append(" and ").append(string3).toString()); + } + } + + public static ImmutableMap copyOf(Map map) { + if (map instanceof ImmutableMap && !(map instanceof ImmutableSortedMap)) { + ImmutableMap kvMap = (ImmutableMap)map; + if (!kvMap.isPartialView()) { + return kvMap; + } + } else if (map instanceof EnumMap) { + return ImmutableMap.copyOfEnumMapUnsafe(map); + } + Map.Entry[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY); + switch (entries.length) { + case 0: { + return ImmutableMap.of(); + } + case 1: { + Map.Entry onlyEntry = entries[0]; + return ImmutableMap.of(onlyEntry.getKey(), onlyEntry.getValue()); + } + } + return new RegularImmutableMap(entries); + } + + private static ImmutableMap copyOfEnumMapUnsafe(Map map) { + return ImmutableMap.copyOfEnumMap((EnumMap)map); + } + + private static , V> ImmutableMap copyOfEnumMap(Map original) { + EnumMap copy = new EnumMap(original); + for (Map.Entry entry : copy.entrySet()) { + CollectPreconditions.checkEntryNotNull(entry.getKey(), entry.getValue()); + } + return ImmutableEnumMap.asImmutable(copy); + } + + ImmutableMap() { + } + + @Override + @Deprecated + public final V put(K k, V v) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final V remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.get(key) != null; + } + + @Override + public boolean containsValue(@Nullable Object value) { + return ((ImmutableCollection)this.values()).contains(value); + } + + @Override + public abstract V get(@Nullable Object var1); + + @Override + public ImmutableSet> entrySet() { + ImmutableSet> result = this.entrySet; + return result == null ? (this.entrySet = this.createEntrySet()) : result; + } + + abstract ImmutableSet> createEntrySet(); + + @Override + public ImmutableSet keySet() { + ImmutableSet result = this.keySet; + return result == null ? (this.keySet = this.createKeySet()) : result; + } + + ImmutableSet createKeySet() { + return new ImmutableMapKeySet(this); + } + + @Override + public ImmutableCollection values() { + ImmutableCollection result = this.values; + return result == null ? (this.values = new ImmutableMapValues(this)) : result; + } + + @Beta + public ImmutableSetMultimap asMultimap() { + ImmutableSetMultimap result = this.multimapView; + return result == null ? (this.multimapView = this.createMultimapView()) : result; + } + + private ImmutableSetMultimap createMultimapView() { + ImmutableMap> map = this.viewMapValuesAsSingletonSets(); + return new ImmutableSetMultimap(map, map.size(), null); + } + + private ImmutableMap> viewMapValuesAsSingletonSets() { + return new MapViewOfValuesAsSingletonSets(this); + } + + @Override + public boolean equals(@Nullable Object object) { + return Maps.equalsImpl(this, object); + } + + abstract boolean isPartialView(); + + @Override + public int hashCode() { + return ((ImmutableSet)this.entrySet()).hashCode(); + } + + public String toString() { + return Maps.toStringImpl(this); + } + + Object writeReplace() { + return new SerializedForm(this); + } + + static class SerializedForm + implements Serializable { + private final Object[] keys; + private final Object[] values; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableMap map) { + this.keys = new Object[map.size()]; + this.values = new Object[map.size()]; + int i = 0; + for (Map.Entry entry : map.entrySet()) { + this.keys[i] = entry.getKey(); + this.values[i] = entry.getValue(); + ++i; + } + } + + Object readResolve() { + Builder builder = new Builder(); + return this.createMap(builder); + } + + Object createMap(Builder builder) { + for (int i = 0; i < this.keys.length; ++i) { + builder.put(this.keys[i], this.values[i]); + } + return builder.build(); + } + } + + private static final class MapViewOfValuesAsSingletonSets + extends ImmutableMap> { + private final ImmutableMap delegate; + + MapViewOfValuesAsSingletonSets(ImmutableMap delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.delegate.containsKey(key); + } + + @Override + public ImmutableSet get(@Nullable Object key) { + V outerValue = this.delegate.get(key); + return outerValue == null ? null : ImmutableSet.of(outerValue); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + ImmutableSet>> createEntrySet() { + return new ImmutableMapEntrySet>(){ + + @Override + ImmutableMap> map() { + return MapViewOfValuesAsSingletonSets.this; + } + + @Override + public UnmodifiableIterator>> iterator() { + final Iterator backingIterator = ((ImmutableSet)MapViewOfValuesAsSingletonSets.this.delegate.entrySet()).iterator(); + return new UnmodifiableIterator>>(){ + + @Override + public boolean hasNext() { + return backingIterator.hasNext(); + } + + @Override + public Map.Entry> next() { + final Map.Entry backingEntry = (Map.Entry)backingIterator.next(); + return new AbstractMapEntry>(){ + + @Override + public K getKey() { + return backingEntry.getKey(); + } + + @Override + public ImmutableSet getValue() { + return ImmutableSet.of(backingEntry.getValue()); + } + }; + } + }; + } + }; + } + } + + public static class Builder { + ImmutableMapEntry.TerminalEntry[] entries; + int size; + + public Builder() { + this(4); + } + + Builder(int initialCapacity) { + this.entries = new ImmutableMapEntry.TerminalEntry[initialCapacity]; + this.size = 0; + } + + private void ensureCapacity(int minCapacity) { + if (minCapacity > this.entries.length) { + this.entries = ObjectArrays.arraysCopyOf(this.entries, ImmutableCollection.Builder.expandedCapacity(this.entries.length, minCapacity)); + } + } + + public Builder put(K key, V value) { + this.ensureCapacity(this.size + 1); + ImmutableMapEntry.TerminalEntry entry = ImmutableMap.entryOf(key, value); + this.entries[this.size++] = entry; + return this; + } + + public Builder put(Map.Entry entry) { + return this.put(entry.getKey(), entry.getValue()); + } + + public Builder putAll(Map map) { + this.ensureCapacity(this.size + map.size()); + for (Map.Entry entry : map.entrySet()) { + this.put(entry); + } + return this; + } + + public ImmutableMap build() { + switch (this.size) { + case 0: { + return ImmutableMap.of(); + } + case 1: { + return ImmutableMap.of(this.entries[0].getKey(), this.entries[0].getValue()); + } + } + return new RegularImmutableMap(this.size, this.entries); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMapEntry.java b/src/com/google/common/collect/ImmutableMapEntry.java new file mode 100644 index 0000000..6eb10ba --- /dev/null +++ b/src/com/google/common/collect/ImmutableMapEntry.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ImmutableEntry; +import javax.annotation.Nullable; + +@GwtIncompatible(value="unnecessary") +abstract class ImmutableMapEntry +extends ImmutableEntry { + ImmutableMapEntry(K key, V value) { + super(key, value); + CollectPreconditions.checkEntryNotNull(key, value); + } + + ImmutableMapEntry(ImmutableMapEntry contents) { + super(contents.getKey(), contents.getValue()); + } + + @Nullable + abstract ImmutableMapEntry getNextInKeyBucket(); + + @Nullable + abstract ImmutableMapEntry getNextInValueBucket(); + + static final class TerminalEntry + extends ImmutableMapEntry { + TerminalEntry(ImmutableMapEntry contents) { + super(contents); + } + + TerminalEntry(K key, V value) { + super(key, value); + } + + @Override + @Nullable + ImmutableMapEntry getNextInKeyBucket() { + return null; + } + + @Override + @Nullable + ImmutableMapEntry getNextInValueBucket() { + return null; + } + } +} diff --git a/src/com/google/common/collect/ImmutableMapEntrySet.java b/src/com/google/common/collect/ImmutableMapEntrySet.java new file mode 100644 index 0000000..e3cb38f --- /dev/null +++ b/src/com/google/common/collect/ImmutableMapEntrySet.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +abstract class ImmutableMapEntrySet +extends ImmutableSet> { + ImmutableMapEntrySet() { + } + + abstract ImmutableMap map(); + + @Override + public int size() { + return this.map().size(); + } + + @Override + public boolean contains(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)object; + V value = this.map().get(entry.getKey()); + return value != null && value.equals(entry.getValue()); + } + return false; + } + + @Override + boolean isPartialView() { + return this.map().isPartialView(); + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new EntrySetSerializedForm(this.map()); + } + + @GwtIncompatible(value="serialization") + private static class EntrySetSerializedForm + implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + EntrySetSerializedForm(ImmutableMap map) { + this.map = map; + } + + Object readResolve() { + return this.map.entrySet(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMapKeySet.java b/src/com/google/common/collect/ImmutableMapKeySet.java new file mode 100644 index 0000000..72d20ec --- /dev/null +++ b/src/com/google/common/collect/ImmutableMapKeySet.java @@ -0,0 +1,84 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class ImmutableMapKeySet +extends ImmutableSet { + private final ImmutableMap map; + + ImmutableMapKeySet(ImmutableMap map) { + this.map = map; + } + + @Override + public int size() { + return this.map.size(); + } + + @Override + public UnmodifiableIterator iterator() { + return this.asList().iterator(); + } + + @Override + public boolean contains(@Nullable Object object) { + return this.map.containsKey(object); + } + + @Override + ImmutableList createAsList() { + final ImmutableList entryList = ((ImmutableCollection)((Object)this.map.entrySet())).asList(); + return new ImmutableAsList(){ + + @Override + public K get(int index) { + return ((Map.Entry)entryList.get(index)).getKey(); + } + + @Override + ImmutableCollection delegateCollection() { + return ImmutableMapKeySet.this; + } + }; + } + + @Override + boolean isPartialView() { + return true; + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new KeySetSerializedForm(this.map); + } + + @GwtIncompatible(value="serialization") + private static class KeySetSerializedForm + implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + KeySetSerializedForm(ImmutableMap map) { + this.map = map; + } + + Object readResolve() { + return this.map.keySet(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMapValues.java b/src/com/google/common/collect/ImmutableMapValues.java new file mode 100644 index 0000000..958212d --- /dev/null +++ b/src/com/google/common/collect/ImmutableMapValues.java @@ -0,0 +1,86 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class ImmutableMapValues +extends ImmutableCollection { + private final ImmutableMap map; + + ImmutableMapValues(ImmutableMap map) { + this.map = map; + } + + @Override + public int size() { + return this.map.size(); + } + + @Override + public UnmodifiableIterator iterator() { + return Maps.valueIterator(((ImmutableSet)this.map.entrySet()).iterator()); + } + + @Override + public boolean contains(@Nullable Object object) { + return object != null && Iterators.contains(this.iterator(), object); + } + + @Override + boolean isPartialView() { + return true; + } + + @Override + ImmutableList createAsList() { + final ImmutableList entryList = ((ImmutableCollection)((Object)this.map.entrySet())).asList(); + return new ImmutableAsList(){ + + @Override + public V get(int index) { + return ((Map.Entry)entryList.get(index)).getValue(); + } + + @Override + ImmutableCollection delegateCollection() { + return ImmutableMapValues.this; + } + }; + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new SerializedForm(this.map); + } + + @GwtIncompatible(value="serialization") + private static class SerializedForm + implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableMap map) { + this.map = map; + } + + Object readResolve() { + return this.map.values(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMultimap.java b/src/com/google/common/collect/ImmutableMultimap.java new file mode 100644 index 0000000..d9fbbee --- /dev/null +++ b/src/com/google/common/collect/ImmutableMultimap.java @@ -0,0 +1,456 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Ordering; +import com.google.common.collect.Serialization; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public abstract class ImmutableMultimap +extends AbstractMultimap +implements Serializable { + final transient ImmutableMap> map; + final transient int size; + private static final long serialVersionUID = 0L; + + public static ImmutableMultimap of() { + return ImmutableListMultimap.of(); + } + + public static ImmutableMultimap of(K k1, V v1) { + return ImmutableListMultimap.of(k1, v1); + } + + public static ImmutableMultimap of(K k1, V v1, K k2, V v2) { + return ImmutableListMultimap.of(k1, v1, k2, v2); + } + + public static ImmutableMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) { + return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3); + } + + public static ImmutableMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4); + } + + public static ImmutableMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); + } + + public static Builder builder() { + return new Builder(); + } + + public static ImmutableMultimap copyOf(Multimap multimap) { + ImmutableMultimap kvMultimap; + if (multimap instanceof ImmutableMultimap && !(kvMultimap = (ImmutableMultimap)multimap).isPartialView()) { + return kvMultimap; + } + return ImmutableListMultimap.copyOf(multimap); + } + + ImmutableMultimap(ImmutableMap> map, int size) { + this.map = map; + this.size = size; + } + + @Override + @Deprecated + public ImmutableCollection removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public ImmutableCollection replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public abstract ImmutableCollection get(K var1); + + public abstract ImmutableMultimap inverse(); + + @Override + @Deprecated + public boolean put(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public boolean putAll(Multimap multimap) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + boolean isPartialView() { + return this.map.isPartialView(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.map.containsKey(key); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return value != null && super.containsValue(value); + } + + @Override + public int size() { + return this.size; + } + + @Override + public ImmutableSet keySet() { + return this.map.keySet(); + } + + @Override + public ImmutableMap> asMap() { + return this.map; + } + + @Override + Map> createAsMap() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableCollection> entries() { + return (ImmutableCollection)super.entries(); + } + + @Override + ImmutableCollection> createEntries() { + return new EntryCollection(this); + } + + @Override + UnmodifiableIterator> entryIterator() { + return new Itr>(){ + + @Override + Map.Entry output(K key, V value) { + return Maps.immutableEntry(key, value); + } + }; + } + + @Override + public ImmutableMultiset keys() { + return (ImmutableMultiset)super.keys(); + } + + @Override + ImmutableMultiset createKeys() { + return new Keys(); + } + + @Override + public ImmutableCollection values() { + return (ImmutableCollection)super.values(); + } + + @Override + ImmutableCollection createValues() { + return new Values(this); + } + + @Override + UnmodifiableIterator valueIterator() { + return new Itr(){ + + @Override + V output(K key, V value) { + return value; + } + }; + } + + private static final class Values + extends ImmutableCollection { + private final transient ImmutableMultimap multimap; + private static final long serialVersionUID = 0L; + + Values(ImmutableMultimap multimap) { + this.multimap = multimap; + } + + @Override + public boolean contains(@Nullable Object object) { + return this.multimap.containsValue(object); + } + + @Override + public UnmodifiableIterator iterator() { + return this.multimap.valueIterator(); + } + + @Override + @GwtIncompatible(value="not present in emulated superclass") + int copyIntoArray(Object[] dst, int offset) { + for (ImmutableCollection valueCollection : this.multimap.map.values()) { + offset = valueCollection.copyIntoArray(dst, offset); + } + return offset; + } + + @Override + public int size() { + return this.multimap.size(); + } + + @Override + boolean isPartialView() { + return true; + } + } + + class Keys + extends ImmutableMultiset { + Keys() { + } + + @Override + public boolean contains(@Nullable Object object) { + return ImmutableMultimap.this.containsKey(object); + } + + @Override + public int count(@Nullable Object element) { + Collection values = ImmutableMultimap.this.map.get(element); + return values == null ? 0 : values.size(); + } + + @Override + public Set elementSet() { + return ImmutableMultimap.this.keySet(); + } + + @Override + public int size() { + return ImmutableMultimap.this.size(); + } + + @Override + Multiset.Entry getEntry(int index) { + Map.Entry entry = (Map.Entry)((ImmutableCollection)((Object)ImmutableMultimap.this.map.entrySet())).asList().get(index); + return Multisets.immutableEntry(entry.getKey(), ((Collection)entry.getValue()).size()); + } + + @Override + boolean isPartialView() { + return true; + } + } + + private abstract class Itr + extends UnmodifiableIterator { + final Iterator>> mapIterator; + K key; + Iterator valueIterator; + + private Itr() { + this.mapIterator = ((ImmutableSet)((ImmutableMap)ImmutableMultimap.this.asMap()).entrySet()).iterator(); + this.key = null; + this.valueIterator = Iterators.emptyIterator(); + } + + abstract T output(K var1, V var2); + + @Override + public boolean hasNext() { + return this.mapIterator.hasNext() || this.valueIterator.hasNext(); + } + + @Override + public T next() { + if (!this.valueIterator.hasNext()) { + Map.Entry mapEntry = this.mapIterator.next(); + this.key = mapEntry.getKey(); + this.valueIterator = mapEntry.getValue().iterator(); + } + return this.output(this.key, this.valueIterator.next()); + } + } + + private static class EntryCollection + extends ImmutableCollection> { + final ImmutableMultimap multimap; + private static final long serialVersionUID = 0L; + + EntryCollection(ImmutableMultimap multimap) { + this.multimap = multimap; + } + + @Override + public UnmodifiableIterator> iterator() { + return this.multimap.entryIterator(); + } + + @Override + boolean isPartialView() { + return this.multimap.isPartialView(); + } + + @Override + public int size() { + return this.multimap.size(); + } + + @Override + public boolean contains(Object object) { + if (object instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)object; + return this.multimap.containsEntry(entry.getKey(), entry.getValue()); + } + return false; + } + } + + @GwtIncompatible(value="java serialization is not supported") + static class FieldSettersHolder { + static final Serialization.FieldSetter MAP_FIELD_SETTER = Serialization.getFieldSetter(ImmutableMultimap.class, "map"); + static final Serialization.FieldSetter SIZE_FIELD_SETTER = Serialization.getFieldSetter(ImmutableMultimap.class, "size"); + static final Serialization.FieldSetter EMPTY_SET_FIELD_SETTER = Serialization.getFieldSetter(ImmutableSetMultimap.class, "emptySet"); + + FieldSettersHolder() { + } + } + + public static class Builder { + Multimap builderMultimap = new BuilderMultimap(); + Comparator keyComparator; + Comparator valueComparator; + + public Builder put(K key, V value) { + CollectPreconditions.checkEntryNotNull(key, value); + this.builderMultimap.put(key, value); + return this; + } + + public Builder put(Map.Entry entry) { + return this.put(entry.getKey(), entry.getValue()); + } + + public Builder putAll(K key, Iterable values) { + if (key == null) { + String string = String.valueOf(Iterables.toString(values)); + throw new NullPointerException(string.length() != 0 ? "null key in entry: null=".concat(string) : new String("null key in entry: null=")); + } + Collection valueList = this.builderMultimap.get(key); + for (V value : values) { + CollectPreconditions.checkEntryNotNull(key, value); + valueList.add(value); + } + return this; + } + + public Builder putAll(K key, V ... values) { + return this.putAll(key, (Iterable)Arrays.asList(values)); + } + + public Builder putAll(Multimap multimap) { + for (Map.Entry> entry : multimap.asMap().entrySet()) { + this.putAll(entry.getKey(), (Iterable)entry.getValue()); + } + return this; + } + + public Builder orderKeysBy(Comparator keyComparator) { + this.keyComparator = Preconditions.checkNotNull(keyComparator); + return this; + } + + public Builder orderValuesBy(Comparator valueComparator) { + this.valueComparator = Preconditions.checkNotNull(valueComparator); + return this; + } + + public ImmutableMultimap build() { + if (this.valueComparator != null) { + for (Collection values : this.builderMultimap.asMap().values()) { + List list = (List)values; + Collections.sort(list, this.valueComparator); + } + } + if (this.keyComparator != null) { + BuilderMultimap sortedCopy = new BuilderMultimap(); + ArrayList>> entries = Lists.newArrayList(this.builderMultimap.asMap().entrySet()); + Collections.sort(entries, Ordering.from(this.keyComparator).onKeys()); + for (Map.Entry entry : entries) { + sortedCopy.putAll(entry.getKey(), (Iterable)entry.getValue()); + } + this.builderMultimap = sortedCopy; + } + return ImmutableMultimap.copyOf(this.builderMultimap); + } + } + + private static class BuilderMultimap + extends AbstractMapBasedMultimap { + private static final long serialVersionUID = 0L; + + BuilderMultimap() { + super(new LinkedHashMap()); + } + + @Override + Collection createCollection() { + return Lists.newArrayList(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableMultiset.java b/src/com/google/common/collect/ImmutableMultiset.java new file mode 100644 index 0000000..1ffee92 --- /dev/null +++ b/src/com/google/common/collect/ImmutableMultiset.java @@ -0,0 +1,374 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.LinkedHashMultiset; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.RegularImmutableMultiset; +import com.google.common.collect.Sets; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableMultiset +extends ImmutableCollection +implements Multiset { + private static final ImmutableMultiset EMPTY = new RegularImmutableMultiset(ImmutableMap.of(), 0); + private transient ImmutableSet> entrySet; + + public static ImmutableMultiset of() { + return EMPTY; + } + + public static ImmutableMultiset of(E element) { + return ImmutableMultiset.copyOfInternal(element); + } + + public static ImmutableMultiset of(E e1, E e2) { + return ImmutableMultiset.copyOfInternal(e1, e2); + } + + public static ImmutableMultiset of(E e1, E e2, E e3) { + return ImmutableMultiset.copyOfInternal(e1, e2, e3); + } + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4) { + return ImmutableMultiset.copyOfInternal(e1, e2, e3, e4); + } + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5) { + return ImmutableMultiset.copyOfInternal(e1, e2, e3, e4, e5); + } + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E ... others) { + return ((Builder)((Builder)((Builder)((Builder)((Builder)((Builder)((Builder)new Builder().add((Object)e1)).add((Object)e2)).add((Object)e3)).add((Object)e4)).add((Object)e5)).add((Object)e6)).add((Object[])others)).build(); + } + + public static ImmutableMultiset copyOf(E[] elements) { + return ImmutableMultiset.copyOf(Arrays.asList(elements)); + } + + public static ImmutableMultiset copyOf(Iterable elements) { + ImmutableMultiset result; + if (elements instanceof ImmutableMultiset && !(result = (ImmutableMultiset)elements).isPartialView()) { + return result; + } + Multiset multiset = elements instanceof Multiset ? Multisets.cast(elements) : LinkedHashMultiset.create(elements); + return ImmutableMultiset.copyOfInternal(multiset); + } + + private static ImmutableMultiset copyOfInternal(E ... elements) { + return ImmutableMultiset.copyOf(Arrays.asList(elements)); + } + + private static ImmutableMultiset copyOfInternal(Multiset multiset) { + return ImmutableMultiset.copyFromEntries(multiset.entrySet()); + } + + static ImmutableMultiset copyFromEntries(Collection> entries) { + long size = 0L; + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Multiset.Entry entry : entries) { + int count = entry.getCount(); + if (count <= 0) continue; + builder.put(entry.getElement(), count); + size += (long)count; + } + if (size == 0L) { + return ImmutableMultiset.of(); + } + return new RegularImmutableMultiset(builder.build(), Ints.saturatedCast(size)); + } + + public static ImmutableMultiset copyOf(Iterator elements) { + LinkedHashMultiset multiset = LinkedHashMultiset.create(); + Iterators.addAll(multiset, elements); + return ImmutableMultiset.copyOfInternal(multiset); + } + + ImmutableMultiset() { + } + + @Override + public UnmodifiableIterator iterator() { + final Iterator entryIterator = ((ImmutableSet)this.entrySet()).iterator(); + return new UnmodifiableIterator(){ + int remaining; + E element; + + @Override + public boolean hasNext() { + return this.remaining > 0 || entryIterator.hasNext(); + } + + @Override + public E next() { + if (this.remaining <= 0) { + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + this.element = entry.getElement(); + this.remaining = entry.getCount(); + } + --this.remaining; + return this.element; + } + }; + } + + @Override + public boolean contains(@Nullable Object object) { + return this.count(object) > 0; + } + + @Override + public boolean containsAll(Collection targets) { + return this.elementSet().containsAll(targets); + } + + @Override + @Deprecated + public final int add(E element, int occurrences) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final int remove(Object element, int occurrences) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final int setCount(E element, int count) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final boolean setCount(E element, int oldCount, int newCount) { + throw new UnsupportedOperationException(); + } + + @Override + @GwtIncompatible(value="not present in emulated superclass") + int copyIntoArray(Object[] dst, int offset) { + for (Multiset.Entry entry : this.entrySet()) { + Arrays.fill(dst, offset, offset + entry.getCount(), entry.getElement()); + offset += entry.getCount(); + } + return offset; + } + + @Override + public boolean equals(@Nullable Object object) { + return Multisets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this.entrySet()); + } + + @Override + public String toString() { + return ((AbstractCollection)((Object)this.entrySet())).toString(); + } + + @Override + public ImmutableSet> entrySet() { + ImmutableSet>> es = this.entrySet; + return es == null ? (this.entrySet = this.createEntrySet()) : es; + } + + private final ImmutableSet> createEntrySet() { + return this.isEmpty() ? ImmutableSet.of() : new EntrySet(); + } + + abstract Multiset.Entry getEntry(int var1); + + @Override + Object writeReplace() { + return new SerializedForm(this); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder + extends ImmutableCollection.Builder { + final Multiset contents; + + public Builder() { + this(LinkedHashMultiset.create()); + } + + Builder(Multiset contents) { + this.contents = contents; + } + + @Override + public Builder add(E element) { + this.contents.add(Preconditions.checkNotNull(element)); + return this; + } + + public Builder addCopies(E element, int occurrences) { + this.contents.add(Preconditions.checkNotNull(element), occurrences); + return this; + } + + public Builder setCount(E element, int count) { + this.contents.setCount(Preconditions.checkNotNull(element), count); + return this; + } + + @Override + public Builder add(E ... elements) { + super.add(elements); + return this; + } + + @Override + public Builder addAll(Iterable elements) { + if (elements instanceof Multiset) { + Multiset multiset = Multisets.cast(elements); + for (Multiset.Entry entry : multiset.entrySet()) { + this.addCopies(entry.getElement(), entry.getCount()); + } + } else { + super.addAll(elements); + } + return this; + } + + @Override + public Builder addAll(Iterator elements) { + super.addAll(elements); + return this; + } + + @Override + public ImmutableMultiset build() { + return ImmutableMultiset.copyOf(this.contents); + } + } + + private static class SerializedForm + implements Serializable { + final Object[] elements; + final int[] counts; + private static final long serialVersionUID = 0L; + + SerializedForm(Multiset multiset) { + int distinct = multiset.entrySet().size(); + this.elements = new Object[distinct]; + this.counts = new int[distinct]; + int i = 0; + for (Multiset.Entry entry : multiset.entrySet()) { + this.elements[i] = entry.getElement(); + this.counts[i] = entry.getCount(); + ++i; + } + } + + Object readResolve() { + LinkedHashMultiset multiset = LinkedHashMultiset.create(this.elements.length); + for (int i = 0; i < this.elements.length; ++i) { + multiset.add(this.elements[i], this.counts[i]); + } + return ImmutableMultiset.copyOf(multiset); + } + } + + static class EntrySetSerializedForm + implements Serializable { + final ImmutableMultiset multiset; + + EntrySetSerializedForm(ImmutableMultiset multiset) { + this.multiset = multiset; + } + + Object readResolve() { + return this.multiset.entrySet(); + } + } + + private final class EntrySet + extends ImmutableSet> { + private static final long serialVersionUID = 0L; + + private EntrySet() { + } + + @Override + boolean isPartialView() { + return ImmutableMultiset.this.isPartialView(); + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new ImmutableAsList>(){ + + @Override + public Multiset.Entry get(int index) { + return ImmutableMultiset.this.getEntry(index); + } + + @Override + ImmutableCollection> delegateCollection() { + return EntrySet.this; + } + }; + } + + @Override + public int size() { + return ImmutableMultiset.this.elementSet().size(); + } + + @Override + public boolean contains(Object o) { + if (o instanceof Multiset.Entry) { + Multiset.Entry entry = (Multiset.Entry)o; + if (entry.getCount() <= 0) { + return false; + } + int count = ImmutableMultiset.this.count(entry.getElement()); + return count == entry.getCount(); + } + return false; + } + + @Override + public int hashCode() { + return ImmutableMultiset.this.hashCode(); + } + + @Override + Object writeReplace() { + return new EntrySetSerializedForm(ImmutableMultiset.this); + } + } +} diff --git a/src/com/google/common/collect/ImmutableRangeMap.java b/src/com/google/common/collect/ImmutableRangeMap.java new file mode 100644 index 0000000..4995c7c --- /dev/null +++ b/src/com/google/common/collect/ImmutableRangeMap.java @@ -0,0 +1,233 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Cut; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.collect.Range; +import com.google.common.collect.RangeMap; +import com.google.common.collect.RangeSet; +import com.google.common.collect.RegularImmutableSortedMap; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.SortedLists; +import com.google.common.collect.TreeRangeMap; +import com.google.common.collect.TreeRangeSet; +import java.util.Map; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + +@Beta +@GwtIncompatible(value="NavigableMap") +public class ImmutableRangeMap, V> +implements RangeMap { + private static final ImmutableRangeMap, Object> EMPTY = new ImmutableRangeMap(ImmutableList.of(), ImmutableList.of()); + private final ImmutableList> ranges; + private final ImmutableList values; + + public static , V> ImmutableRangeMap of() { + return EMPTY; + } + + public static , V> ImmutableRangeMap of(Range range, V value) { + return new ImmutableRangeMap(ImmutableList.of(range), ImmutableList.of(value)); + } + + public static , V> ImmutableRangeMap copyOf(RangeMap rangeMap) { + if (rangeMap instanceof ImmutableRangeMap) { + return (ImmutableRangeMap)rangeMap; + } + Map, V> map = rangeMap.asMapOfRanges(); + ImmutableList.Builder rangesBuilder = new ImmutableList.Builder(map.size()); + ImmutableList.Builder valuesBuilder = new ImmutableList.Builder(map.size()); + for (Map.Entry, V> entry : map.entrySet()) { + rangesBuilder.add(entry.getKey()); + valuesBuilder.add(entry.getValue()); + } + return new ImmutableRangeMap(rangesBuilder.build(), valuesBuilder.build()); + } + + public static , V> Builder builder() { + return new Builder(); + } + + ImmutableRangeMap(ImmutableList> ranges, ImmutableList values) { + this.ranges = ranges; + this.values = values; + } + + @Override + @Nullable + public V get(K key) { + int index = SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), Cut.belowValue(key), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + if (index == -1) { + return null; + } + Range range = (Range)this.ranges.get(index); + return range.contains(key) ? (V)this.values.get(index) : null; + } + + @Override + @Nullable + public Map.Entry, V> getEntry(K key) { + int index = SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), Cut.belowValue(key), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + if (index == -1) { + return null; + } + Range range = (Range)this.ranges.get(index); + return range.contains(key) ? Maps.immutableEntry(range, this.values.get(index)) : null; + } + + @Override + public Range span() { + if (this.ranges.isEmpty()) { + throw new NoSuchElementException(); + } + Range firstRange = (Range)this.ranges.get(0); + Range lastRange = (Range)this.ranges.get(this.ranges.size() - 1); + return Range.create(firstRange.lowerBound, lastRange.upperBound); + } + + @Override + public void put(Range range, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(RangeMap rangeMap) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public void remove(Range range) { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableMap, V> asMapOfRanges() { + if (this.ranges.isEmpty()) { + return ImmutableMap.of(); + } + RegularImmutableSortedSet rangeSet = new RegularImmutableSortedSet(this.ranges, Range.RANGE_LEX_ORDERING); + return new RegularImmutableSortedMap(rangeSet, this.values); + } + + @Override + public ImmutableRangeMap subRangeMap(final Range range) { + int upperIndex; + if (Preconditions.checkNotNull(range).isEmpty()) { + return ImmutableRangeMap.of(); + } + if (this.ranges.isEmpty() || range.encloses(this.span())) { + return this; + } + int lowerIndex = SortedLists.binarySearch(this.ranges, Range.upperBoundFn(), range.lowerBound, SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + if (lowerIndex >= (upperIndex = SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), range.upperBound, SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER))) { + return ImmutableRangeMap.of(); + } + final int off = lowerIndex; + final int len = upperIndex - lowerIndex; + ImmutableList subRanges = new ImmutableList>(){ + + @Override + public int size() { + return len; + } + + @Override + public Range get(int index) { + Preconditions.checkElementIndex(index, len); + if (index == 0 || index == len - 1) { + return ((Range)ImmutableRangeMap.this.ranges.get(index + off)).intersection(range); + } + return (Range)ImmutableRangeMap.this.ranges.get(index + off); + } + + @Override + boolean isPartialView() { + return true; + } + }; + final ImmutableRangeMap outer = this; + return new ImmutableRangeMap(subRanges, (ImmutableList)this.values.subList(lowerIndex, upperIndex)){ + + @Override + public ImmutableRangeMap subRangeMap(Range subRange) { + if (range.isConnected(subRange)) { + return outer.subRangeMap(subRange.intersection(range)); + } + return ImmutableRangeMap.of(); + } + }; + } + + @Override + public int hashCode() { + return ((ImmutableMap)this.asMapOfRanges()).hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof RangeMap) { + RangeMap rangeMap = (RangeMap)o; + return ((ImmutableMap)this.asMapOfRanges()).equals(rangeMap.asMapOfRanges()); + } + return false; + } + + @Override + public String toString() { + return ((ImmutableMap)this.asMapOfRanges()).toString(); + } + + public static final class Builder, V> { + private final RangeSet keyRanges = TreeRangeSet.create(); + private final RangeMap rangeMap = TreeRangeMap.create(); + + public Builder put(Range range, V value) { + Preconditions.checkNotNull(range); + Preconditions.checkNotNull(value); + Preconditions.checkArgument(!range.isEmpty(), "Range must not be empty, but was %s", range); + if (!this.keyRanges.complement().encloses(range)) { + for (Map.Entry, V> entry : this.rangeMap.asMapOfRanges().entrySet()) { + Range key = entry.getKey(); + if (!key.isConnected(range) || key.intersection(range).isEmpty()) continue; + String string = String.valueOf(String.valueOf(range)); + String string2 = String.valueOf(String.valueOf(entry)); + throw new IllegalArgumentException(new StringBuilder(47 + string.length() + string2.length()).append("Overlapping ranges: range ").append(string).append(" overlaps with entry ").append(string2).toString()); + } + } + this.keyRanges.add(range); + this.rangeMap.put(range, value); + return this; + } + + public Builder putAll(RangeMap rangeMap) { + for (Map.Entry, V> entry : rangeMap.asMapOfRanges().entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + return this; + } + + public ImmutableRangeMap build() { + Map, V> map = this.rangeMap.asMapOfRanges(); + ImmutableList.Builder rangesBuilder = new ImmutableList.Builder(map.size()); + ImmutableList.Builder valuesBuilder = new ImmutableList.Builder(map.size()); + for (Map.Entry, V> entry : map.entrySet()) { + rangesBuilder.add(entry.getKey()); + valuesBuilder.add(entry.getValue()); + } + return new ImmutableRangeMap(rangesBuilder.build(), valuesBuilder.build()); + } + } +} diff --git a/src/com/google/common/collect/ImmutableRangeSet.java b/src/com/google/common/collect/ImmutableRangeSet.java new file mode 100644 index 0000000..b878906 --- /dev/null +++ b/src/com/google/common/collect/ImmutableRangeSet.java @@ -0,0 +1,485 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractRangeSet; +import com.google.common.collect.BoundType; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.Cut; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Ordering; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.SortedLists; +import com.google.common.collect.TreeRangeSet; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.Iterator; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + +@Beta +public final class ImmutableRangeSet +extends AbstractRangeSet +implements Serializable { + private static final ImmutableRangeSet> EMPTY = new ImmutableRangeSet(ImmutableList.of()); + private static final ImmutableRangeSet> ALL = new ImmutableRangeSet(ImmutableList.of(Range.all())); + private final transient ImmutableList> ranges; + private transient ImmutableRangeSet complement; + + public static ImmutableRangeSet of() { + return EMPTY; + } + + static ImmutableRangeSet all() { + return ALL; + } + + public static ImmutableRangeSet of(Range range) { + Preconditions.checkNotNull(range); + if (range.isEmpty()) { + return ImmutableRangeSet.of(); + } + if (range.equals(Range.all())) { + return ImmutableRangeSet.all(); + } + return new ImmutableRangeSet(ImmutableList.of(range)); + } + + public static ImmutableRangeSet copyOf(RangeSet rangeSet) { + ImmutableRangeSet immutableRangeSet; + Preconditions.checkNotNull(rangeSet); + if (rangeSet.isEmpty()) { + return ImmutableRangeSet.of(); + } + if (rangeSet.encloses(Range.all())) { + return ImmutableRangeSet.all(); + } + if (rangeSet instanceof ImmutableRangeSet && !(immutableRangeSet = (ImmutableRangeSet)rangeSet).isPartialView()) { + return immutableRangeSet; + } + return new ImmutableRangeSet(ImmutableList.copyOf(rangeSet.asRanges())); + } + + ImmutableRangeSet(ImmutableList> ranges) { + this.ranges = ranges; + } + + private ImmutableRangeSet(ImmutableList> ranges, ImmutableRangeSet complement) { + this.ranges = ranges; + this.complement = complement; + } + + @Override + public boolean encloses(Range otherRange) { + int index = SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), otherRange.lowerBound, Ordering.natural(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + return index != -1 && ((Range)this.ranges.get(index)).encloses(otherRange); + } + + @Override + public Range rangeContaining(C value) { + int index = SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), Cut.belowValue(value), Ordering.natural(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + if (index != -1) { + Range range = (Range)this.ranges.get(index); + return range.contains(value) ? range : null; + } + return null; + } + + @Override + public Range span() { + if (this.ranges.isEmpty()) { + throw new NoSuchElementException(); + } + return Range.create(((Range)this.ranges.get((int)0)).lowerBound, ((Range)this.ranges.get((int)(this.ranges.size() - 1))).upperBound); + } + + @Override + public boolean isEmpty() { + return this.ranges.isEmpty(); + } + + @Override + public void add(Range range) { + throw new UnsupportedOperationException(); + } + + @Override + public void addAll(RangeSet other) { + throw new UnsupportedOperationException(); + } + + @Override + public void remove(Range range) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeAll(RangeSet other) { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableSet> asRanges() { + if (this.ranges.isEmpty()) { + return ImmutableSet.of(); + } + return new RegularImmutableSortedSet>(this.ranges, Range.RANGE_LEX_ORDERING); + } + + @Override + public ImmutableRangeSet complement() { + ImmutableRangeSet result = this.complement; + if (result != null) { + return result; + } + if (this.ranges.isEmpty()) { + this.complement = ImmutableRangeSet.all(); + return this.complement; + } + if (this.ranges.size() == 1 && ((Range)this.ranges.get(0)).equals(Range.all())) { + this.complement = ImmutableRangeSet.of(); + return this.complement; + } + ComplementRanges complementRanges = new ComplementRanges(); + result = this.complement = new ImmutableRangeSet(complementRanges, this); + return result; + } + + private ImmutableList> intersectRanges(final Range range) { + if (this.ranges.isEmpty() || range.isEmpty()) { + return ImmutableList.of(); + } + if (range.encloses(this.span())) { + return this.ranges; + } + final int fromIndex = range.hasLowerBound() ? SortedLists.binarySearch(this.ranges, Range.upperBoundFn(), range.lowerBound, SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER) : 0; + int toIndex = range.hasUpperBound() ? SortedLists.binarySearch(this.ranges, Range.lowerBoundFn(), range.upperBound, SortedLists.KeyPresentBehavior.FIRST_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER) : this.ranges.size(); + final int length = toIndex - fromIndex; + if (length == 0) { + return ImmutableList.of(); + } + return new ImmutableList>(){ + + @Override + public int size() { + return length; + } + + @Override + public Range get(int index) { + Preconditions.checkElementIndex(index, length); + if (index == 0 || index == length - 1) { + return ((Range)ImmutableRangeSet.this.ranges.get(index + fromIndex)).intersection(range); + } + return (Range)ImmutableRangeSet.this.ranges.get(index + fromIndex); + } + + @Override + boolean isPartialView() { + return true; + } + }; + } + + @Override + public ImmutableRangeSet subRangeSet(Range range) { + if (!this.isEmpty()) { + Range span = this.span(); + if (range.encloses(span)) { + return this; + } + if (range.isConnected(span)) { + return new ImmutableRangeSet(this.intersectRanges(range)); + } + } + return ImmutableRangeSet.of(); + } + + public ImmutableSortedSet asSet(DiscreteDomain domain) { + Preconditions.checkNotNull(domain); + if (this.isEmpty()) { + return ImmutableSortedSet.of(); + } + Range span = this.span().canonical(domain); + if (!span.hasLowerBound()) { + throw new IllegalArgumentException("Neither the DiscreteDomain nor this range set are bounded below"); + } + if (!span.hasUpperBound()) { + try { + domain.maxValue(); + } + catch (NoSuchElementException e) { + throw new IllegalArgumentException("Neither the DiscreteDomain nor this range set are bounded above"); + } + } + return new AsSet(domain); + } + + boolean isPartialView() { + return this.ranges.isPartialView(); + } + + public static > Builder builder() { + return new Builder(); + } + + Object writeReplace() { + return new SerializedForm(this.ranges); + } + + private static final class SerializedForm + implements Serializable { + private final ImmutableList> ranges; + + SerializedForm(ImmutableList> ranges) { + this.ranges = ranges; + } + + Object readResolve() { + if (this.ranges.isEmpty()) { + return ImmutableRangeSet.of(); + } + if (this.ranges.equals(ImmutableList.of(Range.all()))) { + return ImmutableRangeSet.all(); + } + return new ImmutableRangeSet(this.ranges); + } + } + + public static class Builder> { + private final RangeSet rangeSet = TreeRangeSet.create(); + + public Builder add(Range range) { + if (range.isEmpty()) { + String string = String.valueOf(String.valueOf(range)); + throw new IllegalArgumentException(new StringBuilder(33 + string.length()).append("range must not be empty, but was ").append(string).toString()); + } + if (!this.rangeSet.complement().encloses(range)) { + for (Range currentRange : this.rangeSet.asRanges()) { + Preconditions.checkArgument(!currentRange.isConnected(range) || currentRange.intersection(range).isEmpty(), "Ranges may not overlap, but received %s and %s", currentRange, range); + } + throw new AssertionError((Object)"should have thrown an IAE above"); + } + this.rangeSet.add(range); + return this; + } + + public Builder addAll(RangeSet ranges) { + for (Range range : ranges.asRanges()) { + this.add(range); + } + return this; + } + + public ImmutableRangeSet build() { + return ImmutableRangeSet.copyOf(this.rangeSet); + } + } + + private static class AsSetSerializedForm + implements Serializable { + private final ImmutableList> ranges; + private final DiscreteDomain domain; + + AsSetSerializedForm(ImmutableList> ranges, DiscreteDomain domain) { + this.ranges = ranges; + this.domain = domain; + } + + Object readResolve() { + return new ImmutableRangeSet(this.ranges).asSet(this.domain); + } + } + + private final class AsSet + extends ImmutableSortedSet { + private final DiscreteDomain domain; + private transient Integer size; + + AsSet(DiscreteDomain domain) { + super(Ordering.natural()); + this.domain = domain; + } + + @Override + public int size() { + Integer result = this.size; + if (result == null) { + Range range; + long total = 0L; + Iterator i$ = ImmutableRangeSet.this.ranges.iterator(); + while (i$.hasNext() && (total += (long)ContiguousSet.create(range = (Range)i$.next(), this.domain).size()) < Integer.MAX_VALUE) { + } + result = this.size = Integer.valueOf(Ints.saturatedCast(total)); + } + return result; + } + + @Override + public UnmodifiableIterator iterator() { + return new AbstractIterator(){ + final Iterator> rangeItr; + Iterator elemItr; + { + this.rangeItr = ImmutableRangeSet.this.ranges.iterator(); + this.elemItr = Iterators.emptyIterator(); + } + + @Override + protected C computeNext() { + while (!this.elemItr.hasNext()) { + if (this.rangeItr.hasNext()) { + this.elemItr = ContiguousSet.create(this.rangeItr.next(), AsSet.this.domain).iterator(); + continue; + } + return (Comparable)this.endOfData(); + } + return (Comparable)this.elemItr.next(); + } + }; + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return new AbstractIterator(){ + final Iterator> rangeItr; + Iterator elemItr; + { + this.rangeItr = ImmutableRangeSet.this.ranges.reverse().iterator(); + this.elemItr = Iterators.emptyIterator(); + } + + @Override + protected C computeNext() { + while (!this.elemItr.hasNext()) { + if (this.rangeItr.hasNext()) { + this.elemItr = ContiguousSet.create(this.rangeItr.next(), AsSet.this.domain).descendingIterator(); + continue; + } + return (Comparable)this.endOfData(); + } + return (Comparable)this.elemItr.next(); + } + }; + } + + ImmutableSortedSet subSet(Range range) { + return ((ImmutableRangeSet)ImmutableRangeSet.this.subRangeSet(range)).asSet(this.domain); + } + + @Override + ImmutableSortedSet headSetImpl(C toElement, boolean inclusive) { + return this.subSet(Range.upTo(toElement, BoundType.forBoolean(inclusive))); + } + + @Override + ImmutableSortedSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) { + if (!fromInclusive && !toInclusive && Range.compareOrThrow(fromElement, toElement) == 0) { + return ImmutableSortedSet.of(); + } + return this.subSet(Range.range(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + @Override + ImmutableSortedSet tailSetImpl(C fromElement, boolean inclusive) { + return this.subSet(Range.downTo(fromElement, BoundType.forBoolean(inclusive))); + } + + @Override + public boolean contains(@Nullable Object o) { + if (o == null) { + return false; + } + try { + Comparable c = (Comparable)o; + return ImmutableRangeSet.this.contains(c); + } + catch (ClassCastException e) { + return false; + } + } + + @Override + int indexOf(Object target) { + if (this.contains(target)) { + Comparable c = (Comparable)target; + long total = 0L; + for (Range range : ImmutableRangeSet.this.ranges) { + if (range.contains(c)) { + return Ints.saturatedCast(total + (long)ContiguousSet.create(range, this.domain).indexOf(c)); + } + total += (long)ContiguousSet.create(range, this.domain).size(); + } + throw new AssertionError((Object)"impossible"); + } + return -1; + } + + @Override + boolean isPartialView() { + return ImmutableRangeSet.this.ranges.isPartialView(); + } + + @Override + public String toString() { + return ImmutableRangeSet.this.ranges.toString(); + } + + @Override + Object writeReplace() { + return new AsSetSerializedForm(ImmutableRangeSet.this.ranges, this.domain); + } + } + + private final class ComplementRanges + extends ImmutableList> { + private final boolean positiveBoundedBelow; + private final boolean positiveBoundedAbove; + private final int size; + + ComplementRanges() { + this.positiveBoundedBelow = ((Range)ImmutableRangeSet.this.ranges.get(0)).hasLowerBound(); + this.positiveBoundedAbove = ((Range)Iterables.getLast(ImmutableRangeSet.this.ranges)).hasUpperBound(); + int size = ImmutableRangeSet.this.ranges.size() - 1; + if (this.positiveBoundedBelow) { + ++size; + } + if (this.positiveBoundedAbove) { + ++size; + } + this.size = size; + } + + @Override + public int size() { + return this.size; + } + + @Override + public Range get(int index) { + Preconditions.checkElementIndex(index, this.size); + Cut lowerBound = this.positiveBoundedBelow ? (index == 0 ? Cut.belowAll() : ((Range)((ImmutableRangeSet)ImmutableRangeSet.this).ranges.get((int)(index - 1))).upperBound) : ((Range)((ImmutableRangeSet)ImmutableRangeSet.this).ranges.get((int)index)).upperBound; + Cut upperBound = this.positiveBoundedAbove && index == this.size - 1 ? Cut.aboveAll() : ((Range)((ImmutableRangeSet)ImmutableRangeSet.this).ranges.get((int)(index + (this.positiveBoundedBelow ? 0 : 1)))).lowerBound; + return Range.create(lowerBound, upperBound); + } + + @Override + boolean isPartialView() { + return true; + } + } +} diff --git a/src/com/google/common/collect/ImmutableSet.java b/src/com/google/common/collect/ImmutableSet.java new file mode 100644 index 0000000..8a2c174 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSet.java @@ -0,0 +1,263 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.EmptyImmutableSet; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableEnumSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.RegularImmutableSet; +import com.google.common.collect.Sets; +import com.google.common.collect.SingletonImmutableSet; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSet +extends ImmutableCollection +implements Set { + static final int MAX_TABLE_SIZE = 0x40000000; + private static final double DESIRED_LOAD_FACTOR = 0.7; + private static final int CUTOFF = 0x2CCCCCCC; + + public static ImmutableSet of() { + return EmptyImmutableSet.INSTANCE; + } + + public static ImmutableSet of(E element) { + return new SingletonImmutableSet(element); + } + + public static ImmutableSet of(E e1, E e2) { + return ImmutableSet.construct(2, e1, e2); + } + + public static ImmutableSet of(E e1, E e2, E e3) { + return ImmutableSet.construct(3, e1, e2, e3); + } + + public static ImmutableSet of(E e1, E e2, E e3, E e4) { + return ImmutableSet.construct(4, e1, e2, e3, e4); + } + + public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5) { + return ImmutableSet.construct(5, e1, e2, e3, e4, e5); + } + + public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5, E e6, E ... others) { + int paramCount = 6; + Object[] elements = new Object[6 + others.length]; + elements[0] = e1; + elements[1] = e2; + elements[2] = e3; + elements[3] = e4; + elements[4] = e5; + elements[5] = e6; + System.arraycopy(others, 0, elements, 6, others.length); + return ImmutableSet.construct(elements.length, elements); + } + + private static ImmutableSet construct(int n, Object ... elements) { + switch (n) { + case 0: { + return ImmutableSet.of(); + } + case 1: { + Object elem = elements[0]; + return ImmutableSet.of(elem); + } + } + int tableSize = ImmutableSet.chooseTableSize(n); + Object[] table = new Object[tableSize]; + int mask = tableSize - 1; + int hashCode = 0; + int uniques = 0; + block4: for (int i = 0; i < n; ++i) { + Object element = ObjectArrays.checkElementNotNull(elements[i], i); + int hash = element.hashCode(); + int j = Hashing.smear(hash); + while (true) { + int index; + Object value; + if ((value = table[index = j & mask]) == null) { + elements[uniques++] = element; + table[index] = element; + hashCode += hash; + continue block4; + } + if (value.equals(element)) continue block4; + ++j; + } + } + Arrays.fill(elements, uniques, n, null); + if (uniques == 1) { + Object element = elements[0]; + return new SingletonImmutableSet(element, hashCode); + } + if (tableSize != ImmutableSet.chooseTableSize(uniques)) { + return ImmutableSet.construct(uniques, elements); + } + Object[] uniqueElements = uniques < elements.length ? ObjectArrays.arraysCopyOf(elements, uniques) : elements; + return new RegularImmutableSet(uniqueElements, hashCode, table, mask); + } + + @VisibleForTesting + static int chooseTableSize(int setSize) { + if (setSize < 0x2CCCCCCC) { + int tableSize = Integer.highestOneBit(setSize - 1) << 1; + while ((double)tableSize * 0.7 < (double)setSize) { + tableSize <<= 1; + } + return tableSize; + } + Preconditions.checkArgument(setSize < 0x40000000, "collection too large"); + return 0x40000000; + } + + public static ImmutableSet copyOf(E[] elements) { + switch (elements.length) { + case 0: { + return ImmutableSet.of(); + } + case 1: { + return ImmutableSet.of(elements[0]); + } + } + return ImmutableSet.construct(elements.length, (Object[])elements.clone()); + } + + public static ImmutableSet copyOf(Iterable elements) { + return elements instanceof Collection ? ImmutableSet.copyOf((Collection)elements) : ImmutableSet.copyOf(elements.iterator()); + } + + public static ImmutableSet copyOf(Iterator elements) { + if (!elements.hasNext()) { + return ImmutableSet.of(); + } + E first = elements.next(); + if (!elements.hasNext()) { + return ImmutableSet.of(first); + } + return ((Builder)((Builder)new Builder().add((Object)first)).addAll(elements)).build(); + } + + public static ImmutableSet copyOf(Collection elements) { + if (elements instanceof ImmutableSet && !(elements instanceof ImmutableSortedSet)) { + ImmutableSet set = (ImmutableSet)elements; + if (!set.isPartialView()) { + return set; + } + } else if (elements instanceof EnumSet) { + return ImmutableSet.copyOfEnumSet((EnumSet)elements); + } + Object[] array = elements.toArray(); + return ImmutableSet.construct(array.length, array); + } + + private static > ImmutableSet copyOfEnumSet(EnumSet enumSet) { + return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet)); + } + + ImmutableSet() { + } + + boolean isHashCodeFast() { + return false; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof ImmutableSet && this.isHashCodeFast() && ((ImmutableSet)object).isHashCodeFast() && this.hashCode() != object.hashCode()) { + return false; + } + return Sets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + @Override + public abstract UnmodifiableIterator iterator(); + + @Override + Object writeReplace() { + return new SerializedForm(this.toArray()); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder + extends ImmutableCollection.ArrayBasedBuilder { + public Builder() { + this(4); + } + + Builder(int capacity) { + super(capacity); + } + + @Override + public Builder add(E element) { + super.add((Object)element); + return this; + } + + @Override + public Builder add(E ... elements) { + super.add(elements); + return this; + } + + @Override + public Builder addAll(Iterable elements) { + super.addAll(elements); + return this; + } + + @Override + public Builder addAll(Iterator elements) { + super.addAll(elements); + return this; + } + + @Override + public ImmutableSet build() { + ImmutableSet result = ImmutableSet.construct(this.size, this.contents); + this.size = result.size(); + return result; + } + } + + private static class SerializedForm + implements Serializable { + final Object[] elements; + private static final long serialVersionUID = 0L; + + SerializedForm(Object[] elements) { + this.elements = elements; + } + + Object readResolve() { + return ImmutableSet.copyOf(this.elements); + } + } +} diff --git a/src/com/google/common/collect/ImmutableSetMultimap.java b/src/com/google/common/collect/ImmutableSetMultimap.java new file mode 100644 index 0000000..ca98d6e --- /dev/null +++ b/src/com/google/common/collect/ImmutableSetMultimap.java @@ -0,0 +1,340 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.EmptyImmutableSetMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.google.common.collect.Ordering; +import com.google.common.collect.Serialization; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import com.google.common.collect.UnmodifiableIterator; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public class ImmutableSetMultimap +extends ImmutableMultimap +implements SetMultimap { + private final transient ImmutableSet emptySet; + private transient ImmutableSetMultimap inverse; + private transient ImmutableSet> entries; + @GwtIncompatible(value="not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static ImmutableSetMultimap of() { + return EmptyImmutableSetMultimap.INSTANCE; + } + + public static ImmutableSetMultimap of(K k1, V v1) { + Builder builder = ImmutableSetMultimap.builder(); + builder.put((Object)k1, (Object)v1); + return builder.build(); + } + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2) { + Builder builder = ImmutableSetMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + return builder.build(); + } + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) { + Builder builder = ImmutableSetMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + return builder.build(); + } + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + Builder builder = ImmutableSetMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + builder.put((Object)k4, (Object)v4); + return builder.build(); + } + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + Builder builder = ImmutableSetMultimap.builder(); + builder.put((Object)k1, (Object)v1); + builder.put((Object)k2, (Object)v2); + builder.put((Object)k3, (Object)v3); + builder.put((Object)k4, (Object)v4); + builder.put((Object)k5, (Object)v5); + return builder.build(); + } + + public static Builder builder() { + return new Builder(); + } + + public static ImmutableSetMultimap copyOf(Multimap multimap) { + return ImmutableSetMultimap.copyOf(multimap, null); + } + + private static ImmutableSetMultimap copyOf(Multimap multimap, Comparator valueComparator) { + ImmutableSetMultimap kvMultimap; + Preconditions.checkNotNull(multimap); + if (multimap.isEmpty() && valueComparator == null) { + return ImmutableSetMultimap.of(); + } + if (multimap instanceof ImmutableSetMultimap && !(kvMultimap = (ImmutableSetMultimap)multimap).isPartialView()) { + return kvMultimap; + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int size = 0; + for (Map.Entry> entry : multimap.asMap().entrySet()) { + K key = entry.getKey(); + Collection values = entry.getValue(); + ImmutableSet set = ImmutableSetMultimap.valueSet(valueComparator, values); + if (set.isEmpty()) continue; + builder.put(key, set); + size += set.size(); + } + return new ImmutableSetMultimap(builder.build(), size, valueComparator); + } + + ImmutableSetMultimap(ImmutableMap> map, int size, @Nullable Comparator valueComparator) { + super(map, size); + this.emptySet = ImmutableSetMultimap.emptySet(valueComparator); + } + + @Override + public ImmutableSet get(@Nullable K key) { + ImmutableSet set = (ImmutableSet)this.map.get(key); + return MoreObjects.firstNonNull(set, this.emptySet); + } + + @Override + public ImmutableSetMultimap inverse() { + ImmutableSetMultimap result = this.inverse; + return result == null ? (this.inverse = this.invert()) : result; + } + + private ImmutableSetMultimap invert() { + Builder builder = ImmutableSetMultimap.builder(); + for (Map.Entry entry : this.entries()) { + builder.put(entry.getValue(), entry.getKey()); + } + ImmutableMultimap invertedMultimap = builder.build(); + ((ImmutableSetMultimap)invertedMultimap).inverse = this; + return invertedMultimap; + } + + @Override + @Deprecated + public ImmutableSet removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public ImmutableSet replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableSet> entries() { + ImmutableSet> result = this.entries; + return result == null ? (this.entries = new EntrySet(this)) : result; + } + + private static ImmutableSet valueSet(@Nullable Comparator valueComparator, Collection values) { + return valueComparator == null ? ImmutableSet.copyOf(values) : ImmutableSortedSet.copyOf(valueComparator, values); + } + + private static ImmutableSet emptySet(@Nullable Comparator valueComparator) { + return valueComparator == null ? ImmutableSet.of() : ImmutableSortedSet.emptySet(valueComparator); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.valueComparator()); + Serialization.writeMultimap(this, stream); + } + + @Nullable + Comparator valueComparator() { + return this.emptySet instanceof ImmutableSortedSet ? ((ImmutableSortedSet)this.emptySet).comparator() : null; + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + ImmutableMap tmpMap; + stream.defaultReadObject(); + Comparator valueComparator = (Comparator)stream.readObject(); + int keyCount = stream.readInt(); + if (keyCount < 0) { + int n = keyCount; + throw new InvalidObjectException(new StringBuilder(29).append("Invalid key count ").append(n).toString()); + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int tmpSize = 0; + for (int i = 0; i < keyCount; ++i) { + Object key = stream.readObject(); + int valueCount = stream.readInt(); + if (valueCount <= 0) { + int n = valueCount; + throw new InvalidObjectException(new StringBuilder(31).append("Invalid value count ").append(n).toString()); + } + Object[] array = new Object[valueCount]; + for (int j = 0; j < valueCount; ++j) { + array[j] = stream.readObject(); + } + ImmutableSet valueSet = ImmutableSetMultimap.valueSet(valueComparator, Arrays.asList(array)); + if (valueSet.size() != array.length) { + String string = String.valueOf(String.valueOf(key)); + throw new InvalidObjectException(new StringBuilder(40 + string.length()).append("Duplicate key-value pairs exist for key ").append(string).toString()); + } + builder.put(key, valueSet); + tmpSize += valueCount; + } + try { + tmpMap = builder.build(); + } + catch (IllegalArgumentException e) { + throw (InvalidObjectException)new InvalidObjectException(e.getMessage()).initCause(e); + } + ImmutableMultimap.FieldSettersHolder.MAP_FIELD_SETTER.set((ImmutableMultimap)this, tmpMap); + ImmutableMultimap.FieldSettersHolder.SIZE_FIELD_SETTER.set((ImmutableMultimap)this, tmpSize); + ImmutableMultimap.FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(this, ImmutableSetMultimap.emptySet(valueComparator)); + } + + private static final class EntrySet + extends ImmutableSet> { + private final transient ImmutableSetMultimap multimap; + + EntrySet(ImmutableSetMultimap multimap) { + this.multimap = multimap; + } + + @Override + public boolean contains(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)object; + return this.multimap.containsEntry(entry.getKey(), entry.getValue()); + } + return false; + } + + @Override + public int size() { + return this.multimap.size(); + } + + @Override + public UnmodifiableIterator> iterator() { + return this.multimap.entryIterator(); + } + + @Override + boolean isPartialView() { + return false; + } + } + + public static final class Builder + extends ImmutableMultimap.Builder { + public Builder() { + this.builderMultimap = new BuilderMultimap(); + } + + @Override + public Builder put(K key, V value) { + this.builderMultimap.put(Preconditions.checkNotNull(key), Preconditions.checkNotNull(value)); + return this; + } + + @Override + public Builder put(Map.Entry entry) { + this.builderMultimap.put(Preconditions.checkNotNull(entry.getKey()), Preconditions.checkNotNull(entry.getValue())); + return this; + } + + @Override + public Builder putAll(K key, Iterable values) { + Collection collection = this.builderMultimap.get(Preconditions.checkNotNull(key)); + for (V value : values) { + collection.add(Preconditions.checkNotNull(value)); + } + return this; + } + + @Override + public Builder putAll(K key, V ... values) { + return this.putAll((Object)key, Arrays.asList(values)); + } + + @Override + public Builder putAll(Multimap multimap) { + for (Map.Entry> entry : multimap.asMap().entrySet()) { + this.putAll((Object)entry.getKey(), entry.getValue()); + } + return this; + } + + @Override + public Builder orderKeysBy(Comparator keyComparator) { + this.keyComparator = Preconditions.checkNotNull(keyComparator); + return this; + } + + @Override + public Builder orderValuesBy(Comparator valueComparator) { + super.orderValuesBy(valueComparator); + return this; + } + + @Override + public ImmutableSetMultimap build() { + if (this.keyComparator != null) { + BuilderMultimap sortedCopy = new BuilderMultimap(); + ArrayList entries = Lists.newArrayList(this.builderMultimap.asMap().entrySet()); + Collections.sort(entries, Ordering.from(this.keyComparator).onKeys()); + for (Map.Entry entry : entries) { + sortedCopy.putAll(entry.getKey(), (Iterable)entry.getValue()); + } + this.builderMultimap = sortedCopy; + } + return ImmutableSetMultimap.copyOf(this.builderMultimap, this.valueComparator); + } + } + + private static class BuilderMultimap + extends AbstractMapBasedMultimap { + private static final long serialVersionUID = 0L; + + BuilderMultimap() { + super(new LinkedHashMap()); + } + + @Override + Collection createCollection() { + return Sets.newLinkedHashSet(); + } + } +} diff --git a/src/com/google/common/collect/ImmutableSortedAsList.java b/src/com/google/common/collect/ImmutableSortedAsList.java new file mode 100644 index 0000000..f426559 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedAsList.java @@ -0,0 +1,57 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.RegularImmutableAsList; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.SortedIterable; +import java.util.Comparator; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class ImmutableSortedAsList +extends RegularImmutableAsList +implements SortedIterable { + ImmutableSortedAsList(ImmutableSortedSet backingSet, ImmutableList backingList) { + super(backingSet, backingList); + } + + @Override + ImmutableSortedSet delegateCollection() { + return (ImmutableSortedSet)super.delegateCollection(); + } + + @Override + public Comparator comparator() { + return ((ImmutableSortedSet)this.delegateCollection()).comparator(); + } + + @Override + @GwtIncompatible(value="ImmutableSortedSet.indexOf") + public int indexOf(@Nullable Object target) { + int index = ((ImmutableSortedSet)this.delegateCollection()).indexOf(target); + return index >= 0 && this.get(index).equals(target) ? index : -1; + } + + @Override + @GwtIncompatible(value="ImmutableSortedSet.indexOf") + public int lastIndexOf(@Nullable Object target) { + return this.indexOf(target); + } + + @Override + public boolean contains(Object target) { + return this.indexOf(target) >= 0; + } + + @Override + @GwtIncompatible(value="super.subListUnchecked does not exist; inherited subList is valid if slow") + ImmutableList subListUnchecked(int fromIndex, int toIndex) { + return new RegularImmutableSortedSet(super.subListUnchecked(fromIndex, toIndex), this.comparator()).asList(); + } +} diff --git a/src/com/google/common/collect/ImmutableSortedMap.java b/src/com/google/common/collect/ImmutableSortedMap.java new file mode 100644 index 0000000..250b3fd --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedMap.java @@ -0,0 +1,367 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.EmptyImmutableSortedMap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMapFauxverideShim; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.RegularImmutableSortedMap; +import com.google.common.collect.RegularImmutableSortedSet; +import java.util.AbstractCollection; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.SortedMap; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSortedMap +extends ImmutableSortedMapFauxverideShim +implements NavigableMap { + private static final Comparator NATURAL_ORDER = Ordering.natural(); + private static final ImmutableSortedMap NATURAL_EMPTY_MAP = new EmptyImmutableSortedMap(NATURAL_ORDER); + private transient ImmutableSortedMap descendingMap; + private static final long serialVersionUID = 0L; + + static ImmutableSortedMap emptyMap(Comparator comparator) { + if (Ordering.natural().equals(comparator)) { + return ImmutableSortedMap.of(); + } + return new EmptyImmutableSortedMap(comparator); + } + + static ImmutableSortedMap fromSortedEntries(Comparator comparator, int size, Map.Entry[] entries) { + if (size == 0) { + return ImmutableSortedMap.emptyMap(comparator); + } + ImmutableList.Builder keyBuilder = ImmutableList.builder(); + ImmutableList.Builder valueBuilder = ImmutableList.builder(); + for (int i = 0; i < size; ++i) { + Map.Entry entry = entries[i]; + keyBuilder.add(entry.getKey()); + valueBuilder.add(entry.getValue()); + } + return new RegularImmutableSortedMap(new RegularImmutableSortedSet(keyBuilder.build(), comparator), valueBuilder.build()); + } + + static ImmutableSortedMap from(ImmutableSortedSet keySet, ImmutableList valueList) { + if (keySet.isEmpty()) { + return ImmutableSortedMap.emptyMap(keySet.comparator()); + } + return new RegularImmutableSortedMap((RegularImmutableSortedSet)keySet, valueList); + } + + public static ImmutableSortedMap of() { + return NATURAL_EMPTY_MAP; + } + + public static , V> ImmutableSortedMap of(K k1, V v1) { + return ImmutableSortedMap.from(ImmutableSortedSet.of(k1), ImmutableList.of(v1)); + } + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2) { + return ImmutableSortedMap.fromEntries(Ordering.natural(), false, 2, ImmutableSortedMap.entryOf(k1, v1), ImmutableSortedMap.entryOf(k2, v2)); + } + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3) { + return ImmutableSortedMap.fromEntries(Ordering.natural(), false, 3, ImmutableSortedMap.entryOf(k1, v1), ImmutableSortedMap.entryOf(k2, v2), ImmutableSortedMap.entryOf(k3, v3)); + } + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return ImmutableSortedMap.fromEntries(Ordering.natural(), false, 4, ImmutableSortedMap.entryOf(k1, v1), ImmutableSortedMap.entryOf(k2, v2), ImmutableSortedMap.entryOf(k3, v3), ImmutableSortedMap.entryOf(k4, v4)); + } + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return ImmutableSortedMap.fromEntries(Ordering.natural(), false, 5, ImmutableSortedMap.entryOf(k1, v1), ImmutableSortedMap.entryOf(k2, v2), ImmutableSortedMap.entryOf(k3, v3), ImmutableSortedMap.entryOf(k4, v4), ImmutableSortedMap.entryOf(k5, v5)); + } + + public static ImmutableSortedMap copyOf(Map map) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedMap.copyOfInternal(map, naturalOrder); + } + + public static ImmutableSortedMap copyOf(Map map, Comparator comparator) { + return ImmutableSortedMap.copyOfInternal(map, Preconditions.checkNotNull(comparator)); + } + + public static ImmutableSortedMap copyOfSorted(SortedMap map) { + Comparator comparator = map.comparator(); + if (comparator == null) { + comparator = NATURAL_ORDER; + } + return ImmutableSortedMap.copyOfInternal(map, comparator); + } + + private static ImmutableSortedMap copyOfInternal(Map map, Comparator comparator) { + ImmutableSortedMap kvMap; + boolean sameComparator = false; + if (map instanceof SortedMap) { + SortedMap sortedMap = (SortedMap)map; + Comparator comparator2 = sortedMap.comparator(); + boolean bl = comparator2 == null ? comparator == NATURAL_ORDER : (sameComparator = comparator.equals(comparator2)); + } + if (sameComparator && map instanceof ImmutableSortedMap && !(kvMap = (ImmutableSortedMap)map).isPartialView()) { + return kvMap; + } + Map.Entry[] entries = map.entrySet().toArray(new Map.Entry[0]); + return ImmutableSortedMap.fromEntries(comparator, sameComparator, entries.length, entries); + } + + static ImmutableSortedMap fromEntries(Comparator comparator, boolean sameComparator, int size, Map.Entry ... entries) { + for (int i = 0; i < size; ++i) { + Map.Entry entry = entries[i]; + entries[i] = ImmutableSortedMap.entryOf(entry.getKey(), entry.getValue()); + } + if (!sameComparator) { + ImmutableSortedMap.sortEntries(comparator, size, entries); + ImmutableSortedMap.validateEntries(size, entries, comparator); + } + return ImmutableSortedMap.fromSortedEntries(comparator, size, entries); + } + + private static void sortEntries(Comparator comparator, int size, Map.Entry[] entries) { + Arrays.sort(entries, 0, size, Ordering.from(comparator).onKeys()); + } + + private static void validateEntries(int size, Map.Entry[] entries, Comparator comparator) { + for (int i = 1; i < size; ++i) { + ImmutableSortedMap.checkNoConflict(comparator.compare(entries[i - 1].getKey(), entries[i].getKey()) != 0, "key", entries[i - 1], entries[i]); + } + } + + public static , V> Builder naturalOrder() { + return new Builder(Ordering.natural()); + } + + public static Builder orderedBy(Comparator comparator) { + return new Builder(comparator); + } + + public static , V> Builder reverseOrder() { + return new Builder(Ordering.natural().reverse()); + } + + ImmutableSortedMap() { + } + + ImmutableSortedMap(ImmutableSortedMap descendingMap) { + this.descendingMap = descendingMap; + } + + @Override + public int size() { + return ((AbstractCollection)this.values()).size(); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return ((ImmutableCollection)this.values()).contains(value); + } + + @Override + boolean isPartialView() { + return this.keySet().isPartialView() || ((ImmutableCollection)this.values()).isPartialView(); + } + + @Override + public ImmutableSet> entrySet() { + return super.entrySet(); + } + + @Override + public abstract ImmutableSortedSet keySet(); + + @Override + public abstract ImmutableCollection values(); + + @Override + public Comparator comparator() { + return ((ImmutableSortedSet)this.keySet()).comparator(); + } + + @Override + public K firstKey() { + return (K)((ImmutableSortedSet)this.keySet()).first(); + } + + @Override + public K lastKey() { + return (K)((ImmutableSortedSet)this.keySet()).last(); + } + + @Override + public ImmutableSortedMap headMap(K toKey) { + return this.headMap((Object)toKey, false); + } + + @Override + public abstract ImmutableSortedMap headMap(K var1, boolean var2); + + @Override + public ImmutableSortedMap subMap(K fromKey, K toKey) { + return this.subMap((Object)fromKey, true, (Object)toKey, false); + } + + @Override + public ImmutableSortedMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + Preconditions.checkNotNull(fromKey); + Preconditions.checkNotNull(toKey); + Preconditions.checkArgument(this.comparator().compare(fromKey, toKey) <= 0, "expected fromKey <= toKey but %s > %s", fromKey, toKey); + return ((ImmutableSortedMap)this.headMap((Object)toKey, toInclusive)).tailMap((Object)fromKey, fromInclusive); + } + + @Override + public ImmutableSortedMap tailMap(K fromKey) { + return this.tailMap((Object)fromKey, true); + } + + @Override + public abstract ImmutableSortedMap tailMap(K var1, boolean var2); + + @Override + public Map.Entry lowerEntry(K key) { + return ((ImmutableSortedMap)this.headMap((Object)key, false)).lastEntry(); + } + + @Override + public K lowerKey(K key) { + return Maps.keyOrNull(this.lowerEntry(key)); + } + + @Override + public Map.Entry floorEntry(K key) { + return ((ImmutableSortedMap)this.headMap((Object)key, true)).lastEntry(); + } + + @Override + public K floorKey(K key) { + return Maps.keyOrNull(this.floorEntry(key)); + } + + @Override + public Map.Entry ceilingEntry(K key) { + return ((ImmutableSortedMap)this.tailMap((Object)key, true)).firstEntry(); + } + + @Override + public K ceilingKey(K key) { + return Maps.keyOrNull(this.ceilingEntry(key)); + } + + @Override + public Map.Entry higherEntry(K key) { + return ((ImmutableSortedMap)this.tailMap((Object)key, false)).firstEntry(); + } + + @Override + public K higherKey(K key) { + return Maps.keyOrNull(this.higherEntry(key)); + } + + @Override + public Map.Entry firstEntry() { + return this.isEmpty() ? null : (Map.Entry)((ImmutableCollection)((Object)this.entrySet())).asList().get(0); + } + + @Override + public Map.Entry lastEntry() { + return this.isEmpty() ? null : (Map.Entry)((ImmutableCollection)((Object)this.entrySet())).asList().get(this.size() - 1); + } + + @Override + @Deprecated + public final Map.Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final Map.Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableSortedMap descendingMap() { + ImmutableSortedMap result = this.descendingMap; + if (result == null) { + result = this.descendingMap = this.createDescendingMap(); + } + return result; + } + + abstract ImmutableSortedMap createDescendingMap(); + + @Override + public ImmutableSortedSet navigableKeySet() { + return this.keySet(); + } + + @Override + public ImmutableSortedSet descendingKeySet() { + return ((ImmutableSortedSet)this.keySet()).descendingSet(); + } + + @Override + Object writeReplace() { + return new SerializedForm(this); + } + + private static class SerializedForm + extends ImmutableMap.SerializedForm { + private final Comparator comparator; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableSortedMap sortedMap) { + super(sortedMap); + this.comparator = sortedMap.comparator(); + } + + @Override + Object readResolve() { + Builder builder = new Builder(this.comparator); + return this.createMap(builder); + } + } + + public static class Builder + extends ImmutableMap.Builder { + private final Comparator comparator; + + public Builder(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + @Override + public Builder put(K key, V value) { + super.put(key, value); + return this; + } + + @Override + public Builder put(Map.Entry entry) { + super.put(entry); + return this; + } + + @Override + public Builder putAll(Map map) { + super.putAll(map); + return this; + } + + @Override + public ImmutableSortedMap build() { + return ImmutableSortedMap.fromEntries(this.comparator, false, this.size, this.entries); + } + } +} diff --git a/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java b/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java new file mode 100644 index 0000000..ae8a712 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedMapFauxverideShim.java @@ -0,0 +1,43 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; + +abstract class ImmutableSortedMapFauxverideShim +extends ImmutableMap { + ImmutableSortedMapFauxverideShim() { + } + + @Deprecated + public static ImmutableSortedMap.Builder builder() { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/ImmutableSortedMultiset.java b/src/com/google/common/collect/ImmutableSortedMultiset.java new file mode 100644 index 0000000..fc2b542 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedMultiset.java @@ -0,0 +1,276 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.DescendingImmutableSortedMultiset; +import com.google.common.collect.EmptyImmutableSortedMultiset; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSortedMultisetFauxverideShim; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.RegularImmutableSortedMultiset; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.SortedMultiset; +import com.google.common.collect.TreeMultiset; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; + +@Beta +@GwtIncompatible(value="hasn't been tested yet") +public abstract class ImmutableSortedMultiset +extends ImmutableSortedMultisetFauxverideShim +implements SortedMultiset { + private static final Comparator NATURAL_ORDER = Ordering.natural(); + private static final ImmutableSortedMultiset NATURAL_EMPTY_MULTISET = new EmptyImmutableSortedMultiset(NATURAL_ORDER); + transient ImmutableSortedMultiset descendingMultiset; + + public static ImmutableSortedMultiset of() { + return NATURAL_EMPTY_MULTISET; + } + + public static > ImmutableSortedMultiset of(E element) { + RegularImmutableSortedSet elementSet = (RegularImmutableSortedSet)ImmutableSortedSet.of(element); + int[] counts = new int[]{1}; + long[] cumulativeCounts = new long[]{0L, 1L}; + return new RegularImmutableSortedMultiset(elementSet, counts, cumulativeCounts, 0, 1); + } + + public static > ImmutableSortedMultiset of(E e1, E e2) { + return ImmutableSortedMultiset.copyOf(Ordering.natural(), Arrays.asList(e1, e2)); + } + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3) { + return ImmutableSortedMultiset.copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3)); + } + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4) { + return ImmutableSortedMultiset.copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4)); + } + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5) { + return ImmutableSortedMultiset.copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4, e5)); + } + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E ... remaining) { + int size = remaining.length + 6; + ArrayList all = Lists.newArrayListWithCapacity(size); + Collections.addAll(all, e1, e2, e3, e4, e5, e6); + Collections.addAll(all, remaining); + return ImmutableSortedMultiset.copyOf(Ordering.natural(), all); + } + + public static > ImmutableSortedMultiset copyOf(E[] elements) { + return ImmutableSortedMultiset.copyOf(Ordering.natural(), Arrays.asList(elements)); + } + + public static ImmutableSortedMultiset copyOf(Iterable elements) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedMultiset.copyOf(naturalOrder, elements); + } + + public static ImmutableSortedMultiset copyOf(Iterator elements) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedMultiset.copyOf(naturalOrder, elements); + } + + public static ImmutableSortedMultiset copyOf(Comparator comparator, Iterator elements) { + Preconditions.checkNotNull(comparator); + return ((Builder)new Builder(comparator).addAll((Iterator)elements)).build(); + } + + public static ImmutableSortedMultiset copyOf(Comparator comparator, Iterable elements) { + ImmutableSortedMultiset multiset; + if (elements instanceof ImmutableSortedMultiset && comparator.equals((multiset = (ImmutableSortedMultiset)elements).comparator())) { + if (multiset.isPartialView()) { + return ImmutableSortedMultiset.copyOfSortedEntries(comparator, ((ImmutableCollection)((Object)multiset.entrySet())).asList()); + } + return multiset; + } + elements = Lists.newArrayList(elements); + TreeMultiset sortedCopy = TreeMultiset.create(Preconditions.checkNotNull(comparator)); + Iterables.addAll(sortedCopy, elements); + return ImmutableSortedMultiset.copyOfSortedEntries(comparator, sortedCopy.entrySet()); + } + + public static ImmutableSortedMultiset copyOfSorted(SortedMultiset sortedMultiset) { + return ImmutableSortedMultiset.copyOfSortedEntries(sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet())); + } + + private static ImmutableSortedMultiset copyOfSortedEntries(Comparator comparator, Collection> entries) { + if (entries.isEmpty()) { + return ImmutableSortedMultiset.emptyMultiset(comparator); + } + ImmutableList.Builder elementsBuilder = new ImmutableList.Builder(entries.size()); + int[] counts = new int[entries.size()]; + long[] cumulativeCounts = new long[entries.size() + 1]; + int i = 0; + for (Multiset.Entry entry : entries) { + elementsBuilder.add((Object)entry.getElement()); + counts[i] = entry.getCount(); + cumulativeCounts[i + 1] = cumulativeCounts[i] + (long)counts[i]; + ++i; + } + return new RegularImmutableSortedMultiset(new RegularImmutableSortedSet(elementsBuilder.build(), comparator), counts, cumulativeCounts, 0, entries.size()); + } + + static ImmutableSortedMultiset emptyMultiset(Comparator comparator) { + if (NATURAL_ORDER.equals(comparator)) { + return NATURAL_EMPTY_MULTISET; + } + return new EmptyImmutableSortedMultiset(comparator); + } + + ImmutableSortedMultiset() { + } + + @Override + public final Comparator comparator() { + return ((ImmutableSortedSet)this.elementSet()).comparator(); + } + + @Override + public abstract ImmutableSortedSet elementSet(); + + @Override + public ImmutableSortedMultiset descendingMultiset() { + ImmutableSortedMultiset result = this.descendingMultiset; + if (result == null) { + this.descendingMultiset = new DescendingImmutableSortedMultiset(this); + return this.descendingMultiset; + } + return result; + } + + @Override + @Deprecated + public final Multiset.Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final Multiset.Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public abstract ImmutableSortedMultiset headMultiset(E var1, BoundType var2); + + @Override + public ImmutableSortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) { + Preconditions.checkArgument(this.comparator().compare(lowerBound, upperBound) <= 0, "Expected lowerBound <= upperBound but %s > %s", lowerBound, upperBound); + return ((ImmutableSortedMultiset)this.tailMultiset((Object)lowerBound, lowerBoundType)).headMultiset((Object)upperBound, upperBoundType); + } + + @Override + public abstract ImmutableSortedMultiset tailMultiset(E var1, BoundType var2); + + public static Builder orderedBy(Comparator comparator) { + return new Builder(comparator); + } + + public static > Builder reverseOrder() { + return new Builder(Ordering.natural().reverse()); + } + + public static > Builder naturalOrder() { + return new Builder(Ordering.natural()); + } + + @Override + Object writeReplace() { + return new SerializedForm(this); + } + + private static final class SerializedForm + implements Serializable { + Comparator comparator; + E[] elements; + int[] counts; + + SerializedForm(SortedMultiset multiset) { + this.comparator = multiset.comparator(); + int n = multiset.entrySet().size(); + this.elements = new Object[n]; + this.counts = new int[n]; + int i = 0; + for (Multiset.Entry entry : multiset.entrySet()) { + this.elements[i] = entry.getElement(); + this.counts[i] = entry.getCount(); + ++i; + } + } + + Object readResolve() { + int n = this.elements.length; + Builder builder = new Builder(this.comparator); + for (int i = 0; i < n; ++i) { + builder.addCopies((Object)this.elements[i], this.counts[i]); + } + return builder.build(); + } + } + + public static class Builder + extends ImmutableMultiset.Builder { + public Builder(Comparator comparator) { + super(TreeMultiset.create(Preconditions.checkNotNull(comparator))); + } + + @Override + public Builder add(E element) { + super.add((Object)element); + return this; + } + + @Override + public Builder addCopies(E element, int occurrences) { + super.addCopies(element, occurrences); + return this; + } + + @Override + public Builder setCount(E element, int count) { + super.setCount(element, count); + return this; + } + + @Override + public Builder add(E ... elements) { + super.add((Object[])elements); + return this; + } + + @Override + public Builder addAll(Iterable elements) { + super.addAll((Iterable)elements); + return this; + } + + @Override + public Builder addAll(Iterator elements) { + super.addAll((Iterator)elements); + return this; + } + + @Override + public ImmutableSortedMultiset build() { + return ImmutableSortedMultiset.copyOfSorted((SortedMultiset)this.contents); + } + } +} diff --git a/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java b/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java new file mode 100644 index 0000000..5c52e80 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java @@ -0,0 +1,53 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSortedMultiset; + +abstract class ImmutableSortedMultisetFauxverideShim +extends ImmutableMultiset { + ImmutableSortedMultisetFauxverideShim() { + } + + @Deprecated + public static ImmutableSortedMultiset.Builder builder() { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E element) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E ... remaining) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedMultiset copyOf(E[] elements) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/ImmutableSortedSet.java b/src/com/google/common/collect/ImmutableSortedSet.java new file mode 100644 index 0000000..02a7986 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedSet.java @@ -0,0 +1,365 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.DescendingImmutableSortedSet; +import com.google.common.collect.EmptyImmutableSortedSet; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSetFauxverideShim; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Ordering; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.SortedIterable; +import com.google.common.collect.SortedIterables; +import com.google.common.collect.UnmodifiableIterator; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSortedSet +extends ImmutableSortedSetFauxverideShim +implements NavigableSet, +SortedIterable { + private static final Comparator NATURAL_ORDER = Ordering.natural(); + private static final ImmutableSortedSet NATURAL_EMPTY_SET = new EmptyImmutableSortedSet(NATURAL_ORDER); + final transient Comparator comparator; + @GwtIncompatible(value="NavigableSet") + transient ImmutableSortedSet descendingSet; + + private static ImmutableSortedSet emptySet() { + return NATURAL_EMPTY_SET; + } + + static ImmutableSortedSet emptySet(Comparator comparator) { + if (NATURAL_ORDER.equals(comparator)) { + return ImmutableSortedSet.emptySet(); + } + return new EmptyImmutableSortedSet(comparator); + } + + public static ImmutableSortedSet of() { + return ImmutableSortedSet.emptySet(); + } + + public static > ImmutableSortedSet of(E element) { + return new RegularImmutableSortedSet(ImmutableList.of(element), Ordering.natural()); + } + + public static > ImmutableSortedSet of(E e1, E e2) { + return ImmutableSortedSet.construct(Ordering.natural(), 2, e1, e2); + } + + public static > ImmutableSortedSet of(E e1, E e2, E e3) { + return ImmutableSortedSet.construct(Ordering.natural(), 3, e1, e2, e3); + } + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4) { + return ImmutableSortedSet.construct(Ordering.natural(), 4, e1, e2, e3, e4); + } + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5) { + return ImmutableSortedSet.construct(Ordering.natural(), 5, e1, e2, e3, e4, e5); + } + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5, E e6, E ... remaining) { + Comparable[] contents = new Comparable[6 + remaining.length]; + contents[0] = e1; + contents[1] = e2; + contents[2] = e3; + contents[3] = e4; + contents[4] = e5; + contents[5] = e6; + System.arraycopy(remaining, 0, contents, 6, remaining.length); + return ImmutableSortedSet.construct(Ordering.natural(), contents.length, contents); + } + + public static > ImmutableSortedSet copyOf(E[] elements) { + return ImmutableSortedSet.construct(Ordering.natural(), elements.length, (Object[])elements.clone()); + } + + public static ImmutableSortedSet copyOf(Iterable elements) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedSet.copyOf(naturalOrder, elements); + } + + public static ImmutableSortedSet copyOf(Collection elements) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedSet.copyOf(naturalOrder, elements); + } + + public static ImmutableSortedSet copyOf(Iterator elements) { + Ordering naturalOrder = Ordering.natural(); + return ImmutableSortedSet.copyOf(naturalOrder, elements); + } + + public static ImmutableSortedSet copyOf(Comparator comparator, Iterator elements) { + return ((Builder)new Builder(comparator).addAll((Iterator)elements)).build(); + } + + public static ImmutableSortedSet copyOf(Comparator comparator, Iterable elements) { + ImmutableSortedSet original; + Preconditions.checkNotNull(comparator); + boolean hasSameComparator = SortedIterables.hasSameComparator(comparator, elements); + if (hasSameComparator && elements instanceof ImmutableSortedSet && !(original = (ImmutableSortedSet)elements).isPartialView()) { + return original; + } + Object[] array = Iterables.toArray(elements); + return ImmutableSortedSet.construct(comparator, array.length, array); + } + + public static ImmutableSortedSet copyOf(Comparator comparator, Collection elements) { + return ImmutableSortedSet.copyOf(comparator, elements); + } + + public static ImmutableSortedSet copyOfSorted(SortedSet sortedSet) { + Comparator comparator = SortedIterables.comparator(sortedSet); + ImmutableList list = ImmutableList.copyOf(sortedSet); + if (list.isEmpty()) { + return ImmutableSortedSet.emptySet(comparator); + } + return new RegularImmutableSortedSet(list, comparator); + } + + static ImmutableSortedSet construct(Comparator comparator, int n, E ... contents) { + if (n == 0) { + return ImmutableSortedSet.emptySet(comparator); + } + ObjectArrays.checkElementsNotNull((Object[])contents, n); + Arrays.sort(contents, 0, n, comparator); + int uniques = 1; + for (int i = 1; i < n; ++i) { + E cur = contents[i]; + E prev = contents[uniques - 1]; + if (comparator.compare(cur, prev) == 0) continue; + contents[uniques++] = cur; + } + Arrays.fill(contents, uniques, n, null); + return new RegularImmutableSortedSet(ImmutableList.asImmutableList(contents, uniques), comparator); + } + + public static Builder orderedBy(Comparator comparator) { + return new Builder(comparator); + } + + public static > Builder reverseOrder() { + return new Builder(Ordering.natural().reverse()); + } + + public static > Builder naturalOrder() { + return new Builder(Ordering.natural()); + } + + int unsafeCompare(Object a, Object b) { + return ImmutableSortedSet.unsafeCompare(this.comparator, a, b); + } + + static int unsafeCompare(Comparator comparator, Object a, Object b) { + Comparator unsafeComparator = comparator; + return unsafeComparator.compare(a, b); + } + + ImmutableSortedSet(Comparator comparator) { + this.comparator = comparator; + } + + @Override + public Comparator comparator() { + return this.comparator; + } + + @Override + public abstract UnmodifiableIterator iterator(); + + @Override + public ImmutableSortedSet headSet(E toElement) { + return this.headSet((Object)toElement, false); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ImmutableSortedSet headSet(E toElement, boolean inclusive) { + return this.headSetImpl(Preconditions.checkNotNull(toElement), inclusive); + } + + @Override + public ImmutableSortedSet subSet(E fromElement, E toElement) { + return this.subSet((Object)fromElement, true, (Object)toElement, false); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ImmutableSortedSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(this.comparator.compare(fromElement, toElement) <= 0); + return this.subSetImpl(fromElement, fromInclusive, toElement, toInclusive); + } + + @Override + public ImmutableSortedSet tailSet(E fromElement) { + return this.tailSet((Object)fromElement, true); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ImmutableSortedSet tailSet(E fromElement, boolean inclusive) { + return this.tailSetImpl(Preconditions.checkNotNull(fromElement), inclusive); + } + + abstract ImmutableSortedSet headSetImpl(E var1, boolean var2); + + abstract ImmutableSortedSet subSetImpl(E var1, boolean var2, E var3, boolean var4); + + abstract ImmutableSortedSet tailSetImpl(E var1, boolean var2); + + @Override + @GwtIncompatible(value="NavigableSet") + public E lower(E e) { + return Iterators.getNext(((ImmutableSortedSet)this.headSet((Object)e, false)).descendingIterator(), null); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public E floor(E e) { + return Iterators.getNext(((ImmutableSortedSet)this.headSet((Object)e, true)).descendingIterator(), null); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public E ceiling(E e) { + return Iterables.getFirst(this.tailSet((Object)e, true), null); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public E higher(E e) { + return Iterables.getFirst(this.tailSet((Object)e, false), null); + } + + @Override + public E first() { + return this.iterator().next(); + } + + @Override + public E last() { + return this.descendingIterator().next(); + } + + @Override + @Deprecated + @GwtIncompatible(value="NavigableSet") + public final E pollFirst() { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + @GwtIncompatible(value="NavigableSet") + public final E pollLast() { + throw new UnsupportedOperationException(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public ImmutableSortedSet descendingSet() { + ImmutableSortedSet result = this.descendingSet; + if (result == null) { + result = this.descendingSet = this.createDescendingSet(); + result.descendingSet = this; + } + return result; + } + + @GwtIncompatible(value="NavigableSet") + ImmutableSortedSet createDescendingSet() { + return new DescendingImmutableSortedSet(this); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public abstract UnmodifiableIterator descendingIterator(); + + abstract int indexOf(@Nullable Object var1); + + private void readObject(ObjectInputStream stream) throws InvalidObjectException { + throw new InvalidObjectException("Use SerializedForm"); + } + + @Override + Object writeReplace() { + return new SerializedForm(this.comparator, this.toArray()); + } + + private static class SerializedForm + implements Serializable { + final Comparator comparator; + final Object[] elements; + private static final long serialVersionUID = 0L; + + public SerializedForm(Comparator comparator, Object[] elements) { + this.comparator = comparator; + this.elements = elements; + } + + Object readResolve() { + return ((Builder)new Builder(this.comparator).add(this.elements)).build(); + } + } + + public static final class Builder + extends ImmutableSet.Builder { + private final Comparator comparator; + + public Builder(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + @Override + public Builder add(E element) { + super.add((Object)element); + return this; + } + + @Override + public Builder add(E ... elements) { + super.add((Object[])elements); + return this; + } + + @Override + public Builder addAll(Iterable elements) { + super.addAll((Iterable)elements); + return this; + } + + @Override + public Builder addAll(Iterator elements) { + super.addAll((Iterator)elements); + return this; + } + + @Override + public ImmutableSortedSet build() { + Object[] contentsArray = this.contents; + ImmutableSortedSet result = ImmutableSortedSet.construct(this.comparator, this.size, contentsArray); + this.size = result.size(); + return result; + } + } +} diff --git a/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java b/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java new file mode 100644 index 0000000..1b83c78 --- /dev/null +++ b/src/com/google/common/collect/ImmutableSortedSetFauxverideShim.java @@ -0,0 +1,53 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; + +abstract class ImmutableSortedSetFauxverideShim +extends ImmutableSet { + ImmutableSortedSetFauxverideShim() { + } + + @Deprecated + public static ImmutableSortedSet.Builder builder() { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E element) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5, E e6, E ... remaining) { + throw new UnsupportedOperationException(); + } + + @Deprecated + public static ImmutableSortedSet copyOf(E[] elements) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/ImmutableTable.java b/src/com/google/common/collect/ImmutableTable.java new file mode 100644 index 0000000..f1e4e10 --- /dev/null +++ b/src/com/google/common/collect/ImmutableTable.java @@ -0,0 +1,215 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractTable; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.RegularImmutableTable; +import com.google.common.collect.SingletonImmutableTable; +import com.google.common.collect.SparseImmutableTable; +import com.google.common.collect.Table; +import com.google.common.collect.Tables; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class ImmutableTable +extends AbstractTable { + private static final ImmutableTable EMPTY = new SparseImmutableTable(ImmutableList.of(), ImmutableSet.of(), ImmutableSet.of()); + + public static ImmutableTable of() { + return EMPTY; + } + + public static ImmutableTable of(R rowKey, C columnKey, V value) { + return new SingletonImmutableTable(rowKey, columnKey, value); + } + + public static ImmutableTable copyOf(Table table) { + if (table instanceof ImmutableTable) { + ImmutableTable parameterizedTable = (ImmutableTable)table; + return parameterizedTable; + } + int size = table.size(); + switch (size) { + case 0: { + return ImmutableTable.of(); + } + case 1: { + Table.Cell onlyCell = Iterables.getOnlyElement(table.cellSet()); + return ImmutableTable.of(onlyCell.getRowKey(), onlyCell.getColumnKey(), onlyCell.getValue()); + } + } + ImmutableSet.Builder cellSetBuilder = ImmutableSet.builder(); + for (Table.Cell cell : table.cellSet()) { + cellSetBuilder.add(ImmutableTable.cellOf(cell.getRowKey(), cell.getColumnKey(), cell.getValue())); + } + return RegularImmutableTable.forCells(cellSetBuilder.build()); + } + + public static Builder builder() { + return new Builder(); + } + + static Table.Cell cellOf(R rowKey, C columnKey, V value) { + return Tables.immutableCell(Preconditions.checkNotNull(rowKey), Preconditions.checkNotNull(columnKey), Preconditions.checkNotNull(value)); + } + + ImmutableTable() { + } + + @Override + public ImmutableSet> cellSet() { + return (ImmutableSet)super.cellSet(); + } + + @Override + abstract ImmutableSet> createCellSet(); + + @Override + final UnmodifiableIterator> cellIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableCollection values() { + return (ImmutableCollection)super.values(); + } + + @Override + abstract ImmutableCollection createValues(); + + @Override + final Iterator valuesIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + public ImmutableMap column(C columnKey) { + Preconditions.checkNotNull(columnKey); + return MoreObjects.firstNonNull((ImmutableMap)((ImmutableMap)this.columnMap()).get(columnKey), ImmutableMap.of()); + } + + @Override + public ImmutableSet columnKeySet() { + return ((ImmutableMap)this.columnMap()).keySet(); + } + + @Override + public abstract ImmutableMap> columnMap(); + + @Override + public ImmutableMap row(R rowKey) { + Preconditions.checkNotNull(rowKey); + return MoreObjects.firstNonNull((ImmutableMap)((ImmutableMap)this.rowMap()).get(rowKey), ImmutableMap.of()); + } + + @Override + public ImmutableSet rowKeySet() { + return ((ImmutableMap)this.rowMap()).keySet(); + } + + @Override + public abstract ImmutableMap> rowMap(); + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + return this.get(rowKey, columnKey) != null; + } + + @Override + public boolean containsValue(@Nullable Object value) { + return ((ImmutableCollection)this.values()).contains(value); + } + + @Override + @Deprecated + public final void clear() { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final V put(R rowKey, C columnKey, V value) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void putAll(Table table) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final V remove(Object rowKey, Object columnKey) { + throw new UnsupportedOperationException(); + } + + public static final class Builder { + private final List> cells = Lists.newArrayList(); + private Comparator rowComparator; + private Comparator columnComparator; + + public Builder orderRowsBy(Comparator rowComparator) { + this.rowComparator = Preconditions.checkNotNull(rowComparator); + return this; + } + + public Builder orderColumnsBy(Comparator columnComparator) { + this.columnComparator = Preconditions.checkNotNull(columnComparator); + return this; + } + + public Builder put(R rowKey, C columnKey, V value) { + this.cells.add(ImmutableTable.cellOf(rowKey, columnKey, value)); + return this; + } + + public Builder put(Table.Cell cell) { + if (cell instanceof Tables.ImmutableCell) { + Preconditions.checkNotNull(cell.getRowKey()); + Preconditions.checkNotNull(cell.getColumnKey()); + Preconditions.checkNotNull(cell.getValue()); + Table.Cell immutableCell = cell; + this.cells.add(immutableCell); + } else { + this.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + return this; + } + + public Builder putAll(Table table) { + for (Table.Cell cell : table.cellSet()) { + this.put(cell); + } + return this; + } + + public ImmutableTable build() { + int size = this.cells.size(); + switch (size) { + case 0: { + return ImmutableTable.of(); + } + case 1: { + return new SingletonImmutableTable(Iterables.getOnlyElement(this.cells)); + } + } + return RegularImmutableTable.forCells(this.cells, this.rowComparator, this.columnComparator); + } + } +} diff --git a/src/com/google/common/collect/Interner.java b/src/com/google/common/collect/Interner.java new file mode 100644 index 0000000..d342bc9 --- /dev/null +++ b/src/com/google/common/collect/Interner.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; + +@Beta +public interface Interner { + public E intern(E var1); +} diff --git a/src/com/google/common/collect/Interners.java b/src/com/google/common/collect/Interners.java new file mode 100644 index 0000000..a2d3e77 --- /dev/null +++ b/src/com/google/common/collect/Interners.java @@ -0,0 +1,93 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Interner; +import com.google.common.collect.MapMaker; +import com.google.common.collect.MapMakerInternalMap; +import java.util.concurrent.ConcurrentMap; + +@Beta +public final class Interners { + private Interners() { + } + + public static Interner newStrongInterner() { + final ConcurrentMap map = new MapMaker().makeMap(); + return new Interner(){ + + @Override + public E intern(E sample) { + Object canonical = map.putIfAbsent(Preconditions.checkNotNull(sample), sample); + return canonical == null ? sample : canonical; + } + }; + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public static Interner newWeakInterner() { + return new WeakInterner(); + } + + public static Function asFunction(Interner interner) { + return new InternerFunction(Preconditions.checkNotNull(interner)); + } + + private static class InternerFunction + implements Function { + private final Interner interner; + + public InternerFunction(Interner interner) { + this.interner = interner; + } + + @Override + public E apply(E input) { + return this.interner.intern(input); + } + + public int hashCode() { + return this.interner.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof InternerFunction) { + InternerFunction that = (InternerFunction)other; + return this.interner.equals(that.interner); + } + return false; + } + } + + private static class WeakInterner + implements Interner { + private final MapMakerInternalMap map = ((MapMaker)new MapMaker().weakKeys().keyEquivalence((Equivalence)Equivalence.equals())).makeCustomMap(); + + private WeakInterner() { + } + + @Override + public E intern(E sample) { + Dummy sneaky; + do { + E canonical; + MapMakerInternalMap.ReferenceEntry entry; + if ((entry = this.map.getEntry(sample)) == null || (canonical = entry.getKey()) == null) continue; + return canonical; + } while ((sneaky = this.map.putIfAbsent(sample, Dummy.VALUE)) != null); + return sample; + } + + private static enum Dummy { + VALUE; + + } + } +} diff --git a/src/com/google/common/collect/Iterables.java b/src/com/google/common/collect/Iterables.java new file mode 100644 index 0000000..aedb566 --- /dev/null +++ b/src/com/google/common/collect/Iterables.java @@ -0,0 +1,532 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Multiset; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.TransformedIterator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.RandomAccess; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Iterables { + private Iterables() { + } + + public static Iterable unmodifiableIterable(Iterable iterable) { + Preconditions.checkNotNull(iterable); + if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) { + return iterable; + } + return new UnmodifiableIterable(iterable); + } + + @Deprecated + public static Iterable unmodifiableIterable(ImmutableCollection iterable) { + return Preconditions.checkNotNull(iterable); + } + + public static int size(Iterable iterable) { + return iterable instanceof Collection ? ((Collection)iterable).size() : Iterators.size(iterable.iterator()); + } + + public static boolean contains(Iterable iterable, @Nullable Object element) { + if (iterable instanceof Collection) { + Collection collection = (Collection)iterable; + return Collections2.safeContains(collection, element); + } + return Iterators.contains(iterable.iterator(), element); + } + + public static boolean removeAll(Iterable removeFrom, Collection elementsToRemove) { + return removeFrom instanceof Collection ? ((Collection)removeFrom).removeAll(Preconditions.checkNotNull(elementsToRemove)) : Iterators.removeAll(removeFrom.iterator(), elementsToRemove); + } + + public static boolean retainAll(Iterable removeFrom, Collection elementsToRetain) { + return removeFrom instanceof Collection ? ((Collection)removeFrom).retainAll(Preconditions.checkNotNull(elementsToRetain)) : Iterators.retainAll(removeFrom.iterator(), elementsToRetain); + } + + public static boolean removeIf(Iterable removeFrom, Predicate predicate) { + if (removeFrom instanceof RandomAccess && removeFrom instanceof List) { + return Iterables.removeIfFromRandomAccessList((List)removeFrom, Preconditions.checkNotNull(predicate)); + } + return Iterators.removeIf(removeFrom.iterator(), predicate); + } + + private static boolean removeIfFromRandomAccessList(List list, Predicate predicate) { + int from; + int to = 0; + for (from = 0; from < list.size(); ++from) { + T element = list.get(from); + if (predicate.apply(element)) continue; + if (from > to) { + try { + list.set(to, element); + } + catch (UnsupportedOperationException e) { + Iterables.slowRemoveIfForRemainingElements(list, predicate, to, from); + return true; + } + } + ++to; + } + list.subList(to, list.size()).clear(); + return from != to; + } + + private static void slowRemoveIfForRemainingElements(List list, Predicate predicate, int to, int from) { + int n; + for (n = list.size() - 1; n > from; --n) { + if (!predicate.apply(list.get(n))) continue; + list.remove(n); + } + for (n = from - 1; n >= to; --n) { + list.remove(n); + } + } + + @Nullable + static T removeFirstMatching(Iterable removeFrom, Predicate predicate) { + Preconditions.checkNotNull(predicate); + Iterator iterator = removeFrom.iterator(); + while (iterator.hasNext()) { + T next = iterator.next(); + if (!predicate.apply(next)) continue; + iterator.remove(); + return next; + } + return null; + } + + public static boolean elementsEqual(Iterable iterable1, Iterable iterable2) { + if (iterable1 instanceof Collection && iterable2 instanceof Collection) { + Collection collection1 = (Collection)iterable1; + Collection collection2 = (Collection)iterable2; + if (collection1.size() != collection2.size()) { + return false; + } + } + return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator()); + } + + public static String toString(Iterable iterable) { + return Iterators.toString(iterable.iterator()); + } + + public static T getOnlyElement(Iterable iterable) { + return Iterators.getOnlyElement(iterable.iterator()); + } + + @Nullable + public static T getOnlyElement(Iterable iterable, @Nullable T defaultValue) { + return Iterators.getOnlyElement(iterable.iterator(), defaultValue); + } + + @GwtIncompatible(value="Array.newInstance(Class, int)") + public static T[] toArray(Iterable iterable, Class type) { + Collection collection = Iterables.toCollection(iterable); + T[] array = ObjectArrays.newArray(type, collection.size()); + return collection.toArray(array); + } + + static Object[] toArray(Iterable iterable) { + return Iterables.toCollection(iterable).toArray(); + } + + private static Collection toCollection(Iterable iterable) { + return iterable instanceof Collection ? (ArrayList)iterable : Lists.newArrayList(iterable.iterator()); + } + + public static boolean addAll(Collection addTo, Iterable elementsToAdd) { + if (elementsToAdd instanceof Collection) { + Collection c = Collections2.cast(elementsToAdd); + return addTo.addAll(c); + } + return Iterators.addAll(addTo, Preconditions.checkNotNull(elementsToAdd).iterator()); + } + + public static int frequency(Iterable iterable, @Nullable Object element) { + if (iterable instanceof Multiset) { + return ((Multiset)iterable).count(element); + } + if (iterable instanceof Set) { + return ((Set)iterable).contains(element) ? 1 : 0; + } + return Iterators.frequency(iterable.iterator(), element); + } + + public static Iterable cycle(final Iterable iterable) { + Preconditions.checkNotNull(iterable); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.cycle(iterable); + } + + @Override + public String toString() { + return String.valueOf(iterable.toString()).concat(" (cycled)"); + } + }; + } + + public static Iterable cycle(T ... elements) { + return Iterables.cycle(Lists.newArrayList(elements)); + } + + public static Iterable concat(Iterable a, Iterable b) { + return Iterables.concat(ImmutableList.of(a, b)); + } + + public static Iterable concat(Iterable a, Iterable b, Iterable c) { + return Iterables.concat(ImmutableList.of(a, b, c)); + } + + public static Iterable concat(Iterable a, Iterable b, Iterable c, Iterable d) { + return Iterables.concat(ImmutableList.of(a, b, c, d)); + } + + public static Iterable concat(Iterable ... inputs) { + return Iterables.concat(ImmutableList.copyOf(inputs)); + } + + public static Iterable concat(final Iterable> inputs) { + Preconditions.checkNotNull(inputs); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.concat(Iterables.iterators(inputs)); + } + }; + } + + private static Iterator> iterators(Iterable> iterables) { + return new TransformedIterator, Iterator>(iterables.iterator()){ + + @Override + Iterator transform(Iterable from) { + return from.iterator(); + } + }; + } + + public static Iterable> partition(final Iterable iterable, final int size) { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(size > 0); + return new FluentIterable>(){ + + @Override + public Iterator> iterator() { + return Iterators.partition(iterable.iterator(), size); + } + }; + } + + public static Iterable> paddedPartition(final Iterable iterable, final int size) { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(size > 0); + return new FluentIterable>(){ + + @Override + public Iterator> iterator() { + return Iterators.paddedPartition(iterable.iterator(), size); + } + }; + } + + public static Iterable filter(final Iterable unfiltered, final Predicate predicate) { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(predicate); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.filter(unfiltered.iterator(), predicate); + } + }; + } + + @GwtIncompatible(value="Class.isInstance") + public static Iterable filter(final Iterable unfiltered, final Class type) { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(type); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.filter(unfiltered.iterator(), type); + } + }; + } + + public static boolean any(Iterable iterable, Predicate predicate) { + return Iterators.any(iterable.iterator(), predicate); + } + + public static boolean all(Iterable iterable, Predicate predicate) { + return Iterators.all(iterable.iterator(), predicate); + } + + public static T find(Iterable iterable, Predicate predicate) { + return Iterators.find(iterable.iterator(), predicate); + } + + @Nullable + public static T find(Iterable iterable, Predicate predicate, @Nullable T defaultValue) { + return Iterators.find(iterable.iterator(), predicate, defaultValue); + } + + public static Optional tryFind(Iterable iterable, Predicate predicate) { + return Iterators.tryFind(iterable.iterator(), predicate); + } + + public static int indexOf(Iterable iterable, Predicate predicate) { + return Iterators.indexOf(iterable.iterator(), predicate); + } + + public static Iterable transform(final Iterable fromIterable, final Function function) { + Preconditions.checkNotNull(fromIterable); + Preconditions.checkNotNull(function); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.transform(fromIterable.iterator(), function); + } + }; + } + + public static T get(Iterable iterable, int position) { + Preconditions.checkNotNull(iterable); + return (T)(iterable instanceof List ? ((List)iterable).get(position) : Iterators.get(iterable.iterator(), position)); + } + + @Nullable + public static T get(Iterable iterable, int position, @Nullable T defaultValue) { + Preconditions.checkNotNull(iterable); + Iterators.checkNonnegative(position); + if (iterable instanceof List) { + List list = Lists.cast(iterable); + return position < list.size() ? list.get(position) : defaultValue; + } + Iterator iterator = iterable.iterator(); + Iterators.advance(iterator, position); + return Iterators.getNext(iterator, defaultValue); + } + + @Nullable + public static T getFirst(Iterable iterable, @Nullable T defaultValue) { + return Iterators.getNext(iterable.iterator(), defaultValue); + } + + public static T getLast(Iterable iterable) { + if (iterable instanceof List) { + List list = (List)iterable; + if (list.isEmpty()) { + throw new NoSuchElementException(); + } + return Iterables.getLastInNonemptyList(list); + } + return Iterators.getLast(iterable.iterator()); + } + + @Nullable + public static T getLast(Iterable iterable, @Nullable T defaultValue) { + if (iterable instanceof Collection) { + Collection c = Collections2.cast(iterable); + if (c.isEmpty()) { + return defaultValue; + } + if (iterable instanceof List) { + return Iterables.getLastInNonemptyList(Lists.cast(iterable)); + } + } + return Iterators.getLast(iterable.iterator(), defaultValue); + } + + private static T getLastInNonemptyList(List list) { + return list.get(list.size() - 1); + } + + public static Iterable skip(final Iterable iterable, final int numberToSkip) { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(numberToSkip >= 0, "number to skip cannot be negative"); + if (iterable instanceof List) { + final List list = (List)iterable; + return new FluentIterable(){ + + @Override + public Iterator iterator() { + int toSkip = Math.min(list.size(), numberToSkip); + return list.subList(toSkip, list.size()).iterator(); + } + }; + } + return new FluentIterable(){ + + @Override + public Iterator iterator() { + final Iterator iterator = iterable.iterator(); + Iterators.advance(iterator, numberToSkip); + return new Iterator(){ + boolean atStart = true; + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + Object result = iterator.next(); + this.atStart = false; + return result; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(!this.atStart); + iterator.remove(); + } + }; + } + }; + } + + public static Iterable limit(final Iterable iterable, final int limitSize) { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(limitSize >= 0, "limit is negative"); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.limit(iterable.iterator(), limitSize); + } + }; + } + + public static Iterable consumingIterable(final Iterable iterable) { + if (iterable instanceof Queue) { + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return new ConsumingQueueIterator((Queue)iterable); + } + + @Override + public String toString() { + return "Iterables.consumingIterable(...)"; + } + }; + } + Preconditions.checkNotNull(iterable); + return new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.consumingIterator(iterable.iterator()); + } + + @Override + public String toString() { + return "Iterables.consumingIterable(...)"; + } + }; + } + + public static boolean isEmpty(Iterable iterable) { + if (iterable instanceof Collection) { + return ((Collection)iterable).isEmpty(); + } + return !iterable.iterator().hasNext(); + } + + @Beta + public static Iterable mergeSorted(final Iterable> iterables, final Comparator comparator) { + Preconditions.checkNotNull(iterables, "iterables"); + Preconditions.checkNotNull(comparator, "comparator"); + FluentIterable iterable = new FluentIterable(){ + + @Override + public Iterator iterator() { + return Iterators.mergeSorted(Iterables.transform(iterables, Iterables.toIterator()), comparator); + } + }; + return new UnmodifiableIterable(iterable); + } + + private static Function, Iterator> toIterator() { + return new Function, Iterator>(){ + + @Override + public Iterator apply(Iterable iterable) { + return iterable.iterator(); + } + }; + } + + private static class ConsumingQueueIterator + extends AbstractIterator { + private final Queue queue; + + private ConsumingQueueIterator(Queue queue) { + this.queue = queue; + } + + @Override + public T computeNext() { + try { + return this.queue.remove(); + } + catch (NoSuchElementException e) { + return this.endOfData(); + } + } + } + + private static final class UnmodifiableIterable + extends FluentIterable { + private final Iterable iterable; + + private UnmodifiableIterable(Iterable iterable) { + this.iterable = iterable; + } + + @Override + public Iterator iterator() { + return Iterators.unmodifiableIterator(this.iterable.iterator()); + } + + @Override + public String toString() { + return this.iterable.toString(); + } + } +} diff --git a/src/com/google/common/collect/Iterators.java b/src/com/google/common/collect/Iterators.java new file mode 100644 index 0000000..5fbfc7f --- /dev/null +++ b/src/com/google/common/collect/Iterators.java @@ -0,0 +1,714 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIndexedListIterator; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.TransformedIterator; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.collect.UnmodifiableListIterator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.PriorityQueue; +import java.util.Queue; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Iterators { + static final UnmodifiableListIterator EMPTY_LIST_ITERATOR = new UnmodifiableListIterator(){ + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + throw new NoSuchElementException(); + } + + @Override + public boolean hasPrevious() { + return false; + } + + @Override + public Object previous() { + throw new NoSuchElementException(); + } + + @Override + public int nextIndex() { + return 0; + } + + @Override + public int previousIndex() { + return -1; + } + }; + private static final Iterator EMPTY_MODIFIABLE_ITERATOR = new Iterator(){ + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + throw new NoSuchElementException(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(false); + } + }; + + private Iterators() { + } + + @Deprecated + public static UnmodifiableIterator emptyIterator() { + return Iterators.emptyListIterator(); + } + + static UnmodifiableListIterator emptyListIterator() { + return EMPTY_LIST_ITERATOR; + } + + static Iterator emptyModifiableIterator() { + return EMPTY_MODIFIABLE_ITERATOR; + } + + public static UnmodifiableIterator unmodifiableIterator(final Iterator iterator) { + Preconditions.checkNotNull(iterator); + if (iterator instanceof UnmodifiableIterator) { + return (UnmodifiableIterator)iterator; + } + return new UnmodifiableIterator(){ + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + return iterator.next(); + } + }; + } + + @Deprecated + public static UnmodifiableIterator unmodifiableIterator(UnmodifiableIterator iterator) { + return Preconditions.checkNotNull(iterator); + } + + public static int size(Iterator iterator) { + int count = 0; + while (iterator.hasNext()) { + iterator.next(); + ++count; + } + return count; + } + + public static boolean contains(Iterator iterator, @Nullable Object element) { + return Iterators.any(iterator, Predicates.equalTo(element)); + } + + public static boolean removeAll(Iterator removeFrom, Collection elementsToRemove) { + return Iterators.removeIf(removeFrom, Predicates.in(elementsToRemove)); + } + + public static boolean removeIf(Iterator removeFrom, Predicate predicate) { + Preconditions.checkNotNull(predicate); + boolean modified = false; + while (removeFrom.hasNext()) { + if (!predicate.apply(removeFrom.next())) continue; + removeFrom.remove(); + modified = true; + } + return modified; + } + + public static boolean retainAll(Iterator removeFrom, Collection elementsToRetain) { + return Iterators.removeIf(removeFrom, Predicates.not(Predicates.in(elementsToRetain))); + } + + public static boolean elementsEqual(Iterator iterator1, Iterator iterator2) { + while (iterator1.hasNext()) { + Object o2; + if (!iterator2.hasNext()) { + return false; + } + Object o1 = iterator1.next(); + if (Objects.equal(o1, o2 = iterator2.next())) continue; + return false; + } + return !iterator2.hasNext(); + } + + public static String toString(Iterator iterator) { + return Collections2.STANDARD_JOINER.appendTo(new StringBuilder().append('['), iterator).append(']').toString(); + } + + public static T getOnlyElement(Iterator iterator) { + T first = iterator.next(); + if (!iterator.hasNext()) { + return first; + } + StringBuilder sb = new StringBuilder(); + String string = String.valueOf(String.valueOf(first)); + sb.append(new StringBuilder(31 + string.length()).append("expected one element but was: <").append(string).toString()); + for (int i = 0; i < 4 && iterator.hasNext(); ++i) { + String string2 = String.valueOf(String.valueOf(iterator.next())); + sb.append(new StringBuilder(2 + string2.length()).append(", ").append(string2).toString()); + } + if (iterator.hasNext()) { + sb.append(", ..."); + } + sb.append('>'); + throw new IllegalArgumentException(sb.toString()); + } + + @Nullable + public static T getOnlyElement(Iterator iterator, @Nullable T defaultValue) { + return iterator.hasNext() ? Iterators.getOnlyElement(iterator) : defaultValue; + } + + @GwtIncompatible(value="Array.newInstance(Class, int)") + public static T[] toArray(Iterator iterator, Class type) { + ArrayList list = Lists.newArrayList(iterator); + return Iterables.toArray(list, type); + } + + public static boolean addAll(Collection addTo, Iterator iterator) { + Preconditions.checkNotNull(addTo); + Preconditions.checkNotNull(iterator); + boolean wasModified = false; + while (iterator.hasNext()) { + wasModified |= addTo.add(iterator.next()); + } + return wasModified; + } + + public static int frequency(Iterator iterator, @Nullable Object element) { + return Iterators.size(Iterators.filter(iterator, Predicates.equalTo(element))); + } + + public static Iterator cycle(final Iterable iterable) { + Preconditions.checkNotNull(iterable); + return new Iterator(){ + Iterator iterator = Iterators.emptyIterator(); + Iterator removeFrom; + + @Override + public boolean hasNext() { + if (!this.iterator.hasNext()) { + this.iterator = iterable.iterator(); + } + return this.iterator.hasNext(); + } + + @Override + public T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.removeFrom = this.iterator; + return this.iterator.next(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.removeFrom != null); + this.removeFrom.remove(); + this.removeFrom = null; + } + }; + } + + public static Iterator cycle(T ... elements) { + return Iterators.cycle(Lists.newArrayList(elements)); + } + + public static Iterator concat(Iterator a, Iterator b) { + return Iterators.concat(ImmutableList.of(a, b).iterator()); + } + + public static Iterator concat(Iterator a, Iterator b, Iterator c) { + return Iterators.concat(ImmutableList.of(a, b, c).iterator()); + } + + public static Iterator concat(Iterator a, Iterator b, Iterator c, Iterator d) { + return Iterators.concat(ImmutableList.of(a, b, c, d).iterator()); + } + + public static Iterator concat(Iterator ... inputs) { + return Iterators.concat(ImmutableList.copyOf(inputs).iterator()); + } + + public static Iterator concat(final Iterator> inputs) { + Preconditions.checkNotNull(inputs); + return new Iterator(){ + Iterator current = Iterators.emptyIterator(); + Iterator removeFrom; + + @Override + public boolean hasNext() { + boolean currentHasNext; + while (!(currentHasNext = Preconditions.checkNotNull(this.current).hasNext()) && inputs.hasNext()) { + this.current = (Iterator)inputs.next(); + } + return currentHasNext; + } + + @Override + public T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.removeFrom = this.current; + return this.current.next(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.removeFrom != null); + this.removeFrom.remove(); + this.removeFrom = null; + } + }; + } + + public static UnmodifiableIterator> partition(Iterator iterator, int size) { + return Iterators.partitionImpl(iterator, size, false); + } + + public static UnmodifiableIterator> paddedPartition(Iterator iterator, int size) { + return Iterators.partitionImpl(iterator, size, true); + } + + private static UnmodifiableIterator> partitionImpl(final Iterator iterator, final int size, final boolean pad) { + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(size > 0); + return new UnmodifiableIterator>(){ + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public List next() { + int count; + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + Object[] array = new Object[size]; + for (count = 0; count < size && iterator.hasNext(); ++count) { + array[count] = iterator.next(); + } + for (int i = count; i < size; ++i) { + array[i] = null; + } + List list = Collections.unmodifiableList(Arrays.asList(array)); + return pad || count == size ? list : list.subList(0, count); + } + }; + } + + public static UnmodifiableIterator filter(final Iterator unfiltered, final Predicate predicate) { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(predicate); + return new AbstractIterator(){ + + @Override + protected T computeNext() { + while (unfiltered.hasNext()) { + Object element = unfiltered.next(); + if (!predicate.apply(element)) continue; + return element; + } + return this.endOfData(); + } + }; + } + + @GwtIncompatible(value="Class.isInstance") + public static UnmodifiableIterator filter(Iterator unfiltered, Class type) { + return Iterators.filter(unfiltered, Predicates.instanceOf(type)); + } + + public static boolean any(Iterator iterator, Predicate predicate) { + return Iterators.indexOf(iterator, predicate) != -1; + } + + public static boolean all(Iterator iterator, Predicate predicate) { + Preconditions.checkNotNull(predicate); + while (iterator.hasNext()) { + T element = iterator.next(); + if (predicate.apply(element)) continue; + return false; + } + return true; + } + + public static T find(Iterator iterator, Predicate predicate) { + return (T)Iterators.filter(iterator, predicate).next(); + } + + @Nullable + public static T find(Iterator iterator, Predicate predicate, @Nullable T defaultValue) { + return Iterators.getNext(Iterators.filter(iterator, predicate), defaultValue); + } + + public static Optional tryFind(Iterator iterator, Predicate predicate) { + UnmodifiableIterator filteredIterator = Iterators.filter(iterator, predicate); + return filteredIterator.hasNext() ? Optional.of(filteredIterator.next()) : Optional.absent(); + } + + public static int indexOf(Iterator iterator, Predicate predicate) { + Preconditions.checkNotNull(predicate, "predicate"); + int i = 0; + while (iterator.hasNext()) { + T current = iterator.next(); + if (predicate.apply(current)) { + return i; + } + ++i; + } + return -1; + } + + public static Iterator transform(Iterator fromIterator, final Function function) { + Preconditions.checkNotNull(function); + return new TransformedIterator(fromIterator){ + + @Override + T transform(F from) { + return function.apply(from); + } + }; + } + + public static T get(Iterator iterator, int position) { + Iterators.checkNonnegative(position); + int skipped = Iterators.advance(iterator, position); + if (!iterator.hasNext()) { + int n = position; + int n2 = skipped; + throw new IndexOutOfBoundsException(new StringBuilder(91).append("position (").append(n).append(") must be less than the number of elements that remained (").append(n2).append(")").toString()); + } + return iterator.next(); + } + + static void checkNonnegative(int position) { + if (position < 0) { + int n = position; + throw new IndexOutOfBoundsException(new StringBuilder(43).append("position (").append(n).append(") must not be negative").toString()); + } + } + + @Nullable + public static T get(Iterator iterator, int position, @Nullable T defaultValue) { + Iterators.checkNonnegative(position); + Iterators.advance(iterator, position); + return Iterators.getNext(iterator, defaultValue); + } + + @Nullable + public static T getNext(Iterator iterator, @Nullable T defaultValue) { + return iterator.hasNext() ? iterator.next() : defaultValue; + } + + public static T getLast(Iterator iterator) { + T current; + do { + current = iterator.next(); + } while (iterator.hasNext()); + return current; + } + + @Nullable + public static T getLast(Iterator iterator, @Nullable T defaultValue) { + return iterator.hasNext() ? Iterators.getLast(iterator) : defaultValue; + } + + public static int advance(Iterator iterator, int numberToAdvance) { + int i; + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(numberToAdvance >= 0, "numberToAdvance must be nonnegative"); + for (i = 0; i < numberToAdvance && iterator.hasNext(); ++i) { + iterator.next(); + } + return i; + } + + public static Iterator limit(final Iterator iterator, final int limitSize) { + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(limitSize >= 0, "limit is negative"); + return new Iterator(){ + private int count; + + @Override + public boolean hasNext() { + return this.count < limitSize && iterator.hasNext(); + } + + @Override + public T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + ++this.count; + return iterator.next(); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + + public static Iterator consumingIterator(final Iterator iterator) { + Preconditions.checkNotNull(iterator); + return new UnmodifiableIterator(){ + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + Object next = iterator.next(); + iterator.remove(); + return next; + } + + public String toString() { + return "Iterators.consumingIterator(...)"; + } + }; + } + + @Nullable + static T pollNext(Iterator iterator) { + if (iterator.hasNext()) { + T result = iterator.next(); + iterator.remove(); + return result; + } + return null; + } + + static void clear(Iterator iterator) { + Preconditions.checkNotNull(iterator); + while (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + public static UnmodifiableIterator forArray(T ... array) { + return Iterators.forArray(array, 0, array.length, 0); + } + + static UnmodifiableListIterator forArray(final T[] array, final int offset, int length, int index) { + Preconditions.checkArgument(length >= 0); + int end = offset + length; + Preconditions.checkPositionIndexes(offset, end, array.length); + Preconditions.checkPositionIndex(index, length); + if (length == 0) { + return Iterators.emptyListIterator(); + } + return new AbstractIndexedListIterator(length, index){ + + @Override + protected T get(int index) { + return array[offset + index]; + } + }; + } + + public static UnmodifiableIterator singletonIterator(final @Nullable T value) { + return new UnmodifiableIterator(){ + boolean done; + + @Override + public boolean hasNext() { + return !this.done; + } + + @Override + public T next() { + if (this.done) { + throw new NoSuchElementException(); + } + this.done = true; + return value; + } + }; + } + + public static UnmodifiableIterator forEnumeration(final Enumeration enumeration) { + Preconditions.checkNotNull(enumeration); + return new UnmodifiableIterator(){ + + @Override + public boolean hasNext() { + return enumeration.hasMoreElements(); + } + + @Override + public T next() { + return enumeration.nextElement(); + } + }; + } + + public static Enumeration asEnumeration(final Iterator iterator) { + Preconditions.checkNotNull(iterator); + return new Enumeration(){ + + @Override + public boolean hasMoreElements() { + return iterator.hasNext(); + } + + @Override + public T nextElement() { + return iterator.next(); + } + }; + } + + public static PeekingIterator peekingIterator(Iterator iterator) { + if (iterator instanceof PeekingImpl) { + PeekingImpl peeking = (PeekingImpl)iterator; + return peeking; + } + return new PeekingImpl(iterator); + } + + @Deprecated + public static PeekingIterator peekingIterator(PeekingIterator iterator) { + return Preconditions.checkNotNull(iterator); + } + + @Beta + public static UnmodifiableIterator mergeSorted(Iterable> iterators, Comparator comparator) { + Preconditions.checkNotNull(iterators, "iterators"); + Preconditions.checkNotNull(comparator, "comparator"); + return new MergingIterator(iterators, comparator); + } + + static ListIterator cast(Iterator iterator) { + return (ListIterator)iterator; + } + + private static class MergingIterator + extends UnmodifiableIterator { + final Queue> queue; + + public MergingIterator(Iterable> iterators, final Comparator itemComparator) { + Comparator heapComparator = new Comparator>(){ + + @Override + public int compare(PeekingIterator o1, PeekingIterator o2) { + return itemComparator.compare(o1.peek(), o2.peek()); + } + }; + this.queue = new PriorityQueue>(2, heapComparator); + for (Iterator iterator : iterators) { + if (!iterator.hasNext()) continue; + this.queue.add(Iterators.peekingIterator(iterator)); + } + } + + @Override + public boolean hasNext() { + return !this.queue.isEmpty(); + } + + @Override + public T next() { + PeekingIterator nextIter = this.queue.remove(); + T next = nextIter.next(); + if (nextIter.hasNext()) { + this.queue.add(nextIter); + } + return next; + } + } + + private static class PeekingImpl + implements PeekingIterator { + private final Iterator iterator; + private boolean hasPeeked; + private E peekedElement; + + public PeekingImpl(Iterator iterator) { + this.iterator = Preconditions.checkNotNull(iterator); + } + + @Override + public boolean hasNext() { + return this.hasPeeked || this.iterator.hasNext(); + } + + @Override + public E next() { + if (!this.hasPeeked) { + return this.iterator.next(); + } + E result = this.peekedElement; + this.hasPeeked = false; + this.peekedElement = null; + return result; + } + + @Override + public void remove() { + Preconditions.checkState(!this.hasPeeked, "Can't remove after you've peeked at next"); + this.iterator.remove(); + } + + @Override + public E peek() { + if (!this.hasPeeked) { + this.peekedElement = this.iterator.next(); + this.hasPeeked = true; + } + return this.peekedElement; + } + } +} diff --git a/src/com/google/common/collect/LexicographicalOrdering.java b/src/com/google/common/collect/LexicographicalOrdering.java new file mode 100644 index 0000000..05213fa --- /dev/null +++ b/src/com/google/common/collect/LexicographicalOrdering.java @@ -0,0 +1,61 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class LexicographicalOrdering +extends Ordering> +implements Serializable { + final Ordering elementOrder; + private static final long serialVersionUID = 0L; + + LexicographicalOrdering(Ordering elementOrder) { + this.elementOrder = elementOrder; + } + + @Override + public int compare(Iterable leftIterable, Iterable rightIterable) { + Iterator left = leftIterable.iterator(); + Iterator right = rightIterable.iterator(); + while (left.hasNext()) { + if (!right.hasNext()) { + return 1; + } + int result = this.elementOrder.compare(left.next(), right.next()); + if (result == 0) continue; + return result; + } + if (right.hasNext()) { + return -1; + } + return 0; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof LexicographicalOrdering) { + LexicographicalOrdering that = (LexicographicalOrdering)object; + return this.elementOrder.equals(that.elementOrder); + } + return false; + } + + public int hashCode() { + return this.elementOrder.hashCode() ^ 0x7BB78CF5; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.elementOrder)); + return new StringBuilder(18 + string.length()).append(string).append(".lexicographical()").toString(); + } +} diff --git a/src/com/google/common/collect/LinkedHashMultimap.java b/src/com/google/common/collect/LinkedHashMultimap.java new file mode 100644 index 0000000..c2b5db0 --- /dev/null +++ b/src/com/google/common/collect/LinkedHashMultimap.java @@ -0,0 +1,443 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.collect.AbstractSetMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableEntry; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public final class LinkedHashMultimap +extends AbstractSetMultimap { + private static final int DEFAULT_KEY_CAPACITY = 16; + private static final int DEFAULT_VALUE_SET_CAPACITY = 2; + @VisibleForTesting + static final double VALUE_SET_LOAD_FACTOR = 1.0; + @VisibleForTesting + transient int valueSetCapacity = 2; + private transient ValueEntry multimapHeaderEntry; + @GwtIncompatible(value="java serialization not supported") + private static final long serialVersionUID = 1L; + + public static LinkedHashMultimap create() { + return new LinkedHashMultimap(16, 2); + } + + public static LinkedHashMultimap create(int expectedKeys, int expectedValuesPerKey) { + return new LinkedHashMultimap(Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey)); + } + + public static LinkedHashMultimap create(Multimap multimap) { + LinkedHashMultimap result = LinkedHashMultimap.create(multimap.keySet().size(), 2); + result.putAll((Multimap)multimap); + return result; + } + + private static void succeedsInValueSet(ValueSetLink pred, ValueSetLink succ) { + pred.setSuccessorInValueSet(succ); + succ.setPredecessorInValueSet(pred); + } + + private static void succeedsInMultimap(ValueEntry pred, ValueEntry succ) { + pred.setSuccessorInMultimap(succ); + succ.setPredecessorInMultimap(pred); + } + + private static void deleteFromValueSet(ValueSetLink entry) { + LinkedHashMultimap.succeedsInValueSet(entry.getPredecessorInValueSet(), entry.getSuccessorInValueSet()); + } + + private static void deleteFromMultimap(ValueEntry entry) { + LinkedHashMultimap.succeedsInMultimap(entry.getPredecessorInMultimap(), entry.getSuccessorInMultimap()); + } + + private LinkedHashMultimap(int keyCapacity, int valueSetCapacity) { + super(new LinkedHashMap(keyCapacity)); + CollectPreconditions.checkNonnegative(valueSetCapacity, "expectedValuesPerKey"); + this.valueSetCapacity = valueSetCapacity; + this.multimapHeaderEntry = new ValueEntry(null, null, 0, null); + LinkedHashMultimap.succeedsInMultimap(this.multimapHeaderEntry, this.multimapHeaderEntry); + } + + @Override + Set createCollection() { + return new LinkedHashSet(this.valueSetCapacity); + } + + @Override + Collection createCollection(K key) { + return new ValueSet(key, this.valueSetCapacity); + } + + @Override + public Set replaceValues(@Nullable K key, Iterable values) { + return super.replaceValues((Object)key, (Iterable)values); + } + + @Override + public Set> entries() { + return super.entries(); + } + + @Override + public Collection values() { + return super.values(); + } + + @Override + Iterator> entryIterator() { + return new Iterator>(){ + ValueEntry nextEntry; + ValueEntry toRemove; + { + this.nextEntry = ((LinkedHashMultimap)LinkedHashMultimap.this).multimapHeaderEntry.successorInMultimap; + } + + @Override + public boolean hasNext() { + return this.nextEntry != LinkedHashMultimap.this.multimapHeaderEntry; + } + + @Override + public Map.Entry next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + ValueEntry result = this.nextEntry; + this.toRemove = result; + this.nextEntry = this.nextEntry.successorInMultimap; + return result; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.toRemove != null); + LinkedHashMultimap.this.remove(this.toRemove.getKey(), this.toRemove.getValue()); + this.toRemove = null; + } + }; + } + + @Override + Iterator valueIterator() { + return Maps.valueIterator(this.entryIterator()); + } + + @Override + public void clear() { + super.clear(); + LinkedHashMultimap.succeedsInMultimap(this.multimapHeaderEntry, this.multimapHeaderEntry); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeInt(this.valueSetCapacity); + stream.writeInt(this.keySet().size()); + for (Object key : this.keySet()) { + stream.writeObject(key); + } + stream.writeInt(this.size()); + for (Map.Entry entry : this.entries()) { + stream.writeObject(entry.getKey()); + stream.writeObject(entry.getValue()); + } + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.multimapHeaderEntry = new ValueEntry(null, null, 0, null); + LinkedHashMultimap.succeedsInMultimap(this.multimapHeaderEntry, this.multimapHeaderEntry); + this.valueSetCapacity = stream.readInt(); + int distinctKeys = stream.readInt(); + LinkedHashMap> map = new LinkedHashMap>(Maps.capacity(distinctKeys)); + for (int i = 0; i < distinctKeys; ++i) { + Object key = stream.readObject(); + map.put(key, this.createCollection(key)); + } + int entries = stream.readInt(); + for (int i = 0; i < entries; ++i) { + Object key = stream.readObject(); + Object value = stream.readObject(); + ((Collection)map.get(key)).add(value); + } + this.setMap(map); + } + + @VisibleForTesting + final class ValueSet + extends Sets.ImprovedAbstractSet + implements ValueSetLink { + private final K key; + @VisibleForTesting + ValueEntry[] hashTable; + private int size = 0; + private int modCount = 0; + private ValueSetLink firstEntry; + private ValueSetLink lastEntry; + + ValueSet(K key, int expectedValues) { + this.key = key; + this.firstEntry = this; + this.lastEntry = this; + int tableSize = Hashing.closedTableSize(expectedValues, 1.0); + ValueEntry[] hashTable = new ValueEntry[tableSize]; + this.hashTable = hashTable; + } + + private int mask() { + return this.hashTable.length - 1; + } + + @Override + public ValueSetLink getPredecessorInValueSet() { + return this.lastEntry; + } + + @Override + public ValueSetLink getSuccessorInValueSet() { + return this.firstEntry; + } + + @Override + public void setPredecessorInValueSet(ValueSetLink entry) { + this.lastEntry = entry; + } + + @Override + public void setSuccessorInValueSet(ValueSetLink entry) { + this.firstEntry = entry; + } + + @Override + public Iterator iterator() { + return new Iterator(){ + ValueSetLink nextEntry; + ValueEntry toRemove; + int expectedModCount; + { + this.nextEntry = ValueSet.this.firstEntry; + this.expectedModCount = ValueSet.this.modCount; + } + + private void checkForComodification() { + if (ValueSet.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + @Override + public boolean hasNext() { + this.checkForComodification(); + return this.nextEntry != ValueSet.this; + } + + @Override + public V next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + ValueEntry entry = (ValueEntry)this.nextEntry; + Object result = entry.getValue(); + this.toRemove = entry; + this.nextEntry = entry.getSuccessorInValueSet(); + return result; + } + + @Override + public void remove() { + this.checkForComodification(); + CollectPreconditions.checkRemove(this.toRemove != null); + ValueSet.this.remove(this.toRemove.getValue()); + this.expectedModCount = ValueSet.this.modCount; + this.toRemove = null; + } + }; + } + + @Override + public int size() { + return this.size; + } + + @Override + public boolean contains(@Nullable Object o) { + int smearedHash = Hashing.smearedHash(o); + ValueEntry entry = this.hashTable[smearedHash & this.mask()]; + while (entry != null) { + if (entry.matchesValue(o, smearedHash)) { + return true; + } + entry = entry.nextInValueBucket; + } + return false; + } + + @Override + public boolean add(@Nullable V value) { + ValueEntry rowHead; + int smearedHash = Hashing.smearedHash(value); + int bucket = smearedHash & this.mask(); + ValueEntry entry = rowHead = this.hashTable[bucket]; + while (entry != null) { + if (entry.matchesValue(value, smearedHash)) { + return false; + } + entry = entry.nextInValueBucket; + } + ValueEntry newEntry = new ValueEntry(this.key, value, smearedHash, rowHead); + LinkedHashMultimap.succeedsInValueSet(this.lastEntry, newEntry); + LinkedHashMultimap.succeedsInValueSet(newEntry, this); + LinkedHashMultimap.succeedsInMultimap(LinkedHashMultimap.this.multimapHeaderEntry.getPredecessorInMultimap(), newEntry); + LinkedHashMultimap.succeedsInMultimap(newEntry, LinkedHashMultimap.this.multimapHeaderEntry); + this.hashTable[bucket] = newEntry; + ++this.size; + ++this.modCount; + this.rehashIfNecessary(); + return true; + } + + private void rehashIfNecessary() { + if (Hashing.needsResizing(this.size, this.hashTable.length, 1.0)) { + ValueEntry[] hashTable = new ValueEntry[this.hashTable.length * 2]; + this.hashTable = hashTable; + int mask = hashTable.length - 1; + for (ValueSetLink entry = this.firstEntry; entry != this; entry = entry.getSuccessorInValueSet()) { + ValueEntry valueEntry = (ValueEntry)entry; + int bucket = valueEntry.smearedValueHash & mask; + valueEntry.nextInValueBucket = hashTable[bucket]; + hashTable[bucket] = valueEntry; + } + } + } + + @Override + public boolean remove(@Nullable Object o) { + int smearedHash = Hashing.smearedHash(o); + int bucket = smearedHash & this.mask(); + ValueEntry prev = null; + ValueEntry entry = this.hashTable[bucket]; + while (entry != null) { + if (entry.matchesValue(o, smearedHash)) { + if (prev == null) { + this.hashTable[bucket] = entry.nextInValueBucket; + } else { + prev.nextInValueBucket = entry.nextInValueBucket; + } + LinkedHashMultimap.deleteFromValueSet(entry); + LinkedHashMultimap.deleteFromMultimap(entry); + --this.size; + ++this.modCount; + return true; + } + prev = entry; + entry = entry.nextInValueBucket; + } + return false; + } + + @Override + public void clear() { + Arrays.fill(this.hashTable, null); + this.size = 0; + for (ValueSetLink entry = this.firstEntry; entry != this; entry = entry.getSuccessorInValueSet()) { + ValueEntry valueEntry = (ValueEntry)entry; + LinkedHashMultimap.deleteFromMultimap(valueEntry); + } + LinkedHashMultimap.succeedsInValueSet(this, this); + ++this.modCount; + } + } + + @VisibleForTesting + static final class ValueEntry + extends ImmutableEntry + implements ValueSetLink { + final int smearedValueHash; + @Nullable + ValueEntry nextInValueBucket; + ValueSetLink predecessorInValueSet; + ValueSetLink successorInValueSet; + ValueEntry predecessorInMultimap; + ValueEntry successorInMultimap; + + ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash, @Nullable ValueEntry nextInValueBucket) { + super(key, value); + this.smearedValueHash = smearedValueHash; + this.nextInValueBucket = nextInValueBucket; + } + + boolean matchesValue(@Nullable Object v, int smearedVHash) { + return this.smearedValueHash == smearedVHash && Objects.equal(this.getValue(), v); + } + + @Override + public ValueSetLink getPredecessorInValueSet() { + return this.predecessorInValueSet; + } + + @Override + public ValueSetLink getSuccessorInValueSet() { + return this.successorInValueSet; + } + + @Override + public void setPredecessorInValueSet(ValueSetLink entry) { + this.predecessorInValueSet = entry; + } + + @Override + public void setSuccessorInValueSet(ValueSetLink entry) { + this.successorInValueSet = entry; + } + + public ValueEntry getPredecessorInMultimap() { + return this.predecessorInMultimap; + } + + public ValueEntry getSuccessorInMultimap() { + return this.successorInMultimap; + } + + public void setSuccessorInMultimap(ValueEntry multimapSuccessor) { + this.successorInMultimap = multimapSuccessor; + } + + public void setPredecessorInMultimap(ValueEntry multimapPredecessor) { + this.predecessorInMultimap = multimapPredecessor; + } + } + + private static interface ValueSetLink { + public ValueSetLink getPredecessorInValueSet(); + + public ValueSetLink getSuccessorInValueSet(); + + public void setPredecessorInValueSet(ValueSetLink var1); + + public void setSuccessorInValueSet(ValueSetLink var1); + } +} diff --git a/src/com/google/common/collect/LinkedHashMultiset.java b/src/com/google/common/collect/LinkedHashMultiset.java new file mode 100644 index 0000000..8c1d47e --- /dev/null +++ b/src/com/google/common/collect/LinkedHashMultiset.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.AbstractMapBasedMultiset; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.Multisets; +import com.google.common.collect.Serialization; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.LinkedHashMap; + +@GwtCompatible(serializable=true, emulated=true) +public final class LinkedHashMultiset +extends AbstractMapBasedMultiset { + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static LinkedHashMultiset create() { + return new LinkedHashMultiset(); + } + + public static LinkedHashMultiset create(int distinctElements) { + return new LinkedHashMultiset(distinctElements); + } + + public static LinkedHashMultiset create(Iterable elements) { + LinkedHashMultiset multiset = LinkedHashMultiset.create(Multisets.inferDistinctElements(elements)); + Iterables.addAll(multiset, elements); + return multiset; + } + + private LinkedHashMultiset() { + super(new LinkedHashMap()); + } + + private LinkedHashMultiset(int distinctElements) { + super(new LinkedHashMap(Maps.capacity(distinctElements))); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + int distinctElements = Serialization.readCount(stream); + this.setBackingMap(new LinkedHashMap(Maps.capacity(distinctElements))); + Serialization.populateMultiset(this, stream, distinctElements); + } +} diff --git a/src/com/google/common/collect/LinkedListMultimap.java b/src/com/google/common/collect/LinkedListMultimap.java new file mode 100644 index 0000000..d066db4 --- /dev/null +++ b/src/com/google/common/collect/LinkedListMultimap.java @@ -0,0 +1,659 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Iterators; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Sets; +import com.google.common.collect.TransformedListIterator; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.AbstractSequentialList; +import java.util.Collection; +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public class LinkedListMultimap +extends AbstractMultimap +implements ListMultimap, +Serializable { + private transient Node head; + private transient Node tail; + private transient Map> keyToKeyList; + private transient int size; + private transient int modCount; + @GwtIncompatible(value="java serialization not supported") + private static final long serialVersionUID = 0L; + + public static LinkedListMultimap create() { + return new LinkedListMultimap(); + } + + public static LinkedListMultimap create(int expectedKeys) { + return new LinkedListMultimap(expectedKeys); + } + + public static LinkedListMultimap create(Multimap multimap) { + return new LinkedListMultimap(multimap); + } + + LinkedListMultimap() { + this.keyToKeyList = Maps.newHashMap(); + } + + private LinkedListMultimap(int expectedKeys) { + this.keyToKeyList = new HashMap>(expectedKeys); + } + + private LinkedListMultimap(Multimap multimap) { + this(multimap.keySet().size()); + this.putAll((Multimap)multimap); + } + + private Node addNode(@Nullable K key, @Nullable V value, @Nullable Node nextSibling) { + Node node = new Node(key, value); + if (this.head == null) { + this.tail = node; + this.head = this.tail; + this.keyToKeyList.put(key, new KeyList(node)); + ++this.modCount; + } else if (nextSibling == null) { + this.tail.next = node; + node.previous = this.tail; + this.tail = node; + KeyList keyList = this.keyToKeyList.get(key); + if (keyList == null) { + keyList = new KeyList(node); + this.keyToKeyList.put(key, keyList); + ++this.modCount; + } else { + ++keyList.count; + Node keyTail = keyList.tail; + keyTail.nextSibling = node; + node.previousSibling = keyTail; + keyList.tail = node; + } + } else { + KeyList keyList = this.keyToKeyList.get(key); + ++keyList.count; + node.previous = nextSibling.previous; + node.previousSibling = nextSibling.previousSibling; + node.next = nextSibling; + node.nextSibling = nextSibling; + if (nextSibling.previousSibling == null) { + this.keyToKeyList.get(key).head = node; + } else { + nextSibling.previousSibling.nextSibling = node; + } + if (nextSibling.previous == null) { + this.head = node; + } else { + nextSibling.previous.next = node; + } + nextSibling.previous = node; + nextSibling.previousSibling = node; + } + ++this.size; + return node; + } + + private void removeNode(Node node) { + if (node.previous != null) { + node.previous.next = node.next; + } else { + this.head = node.next; + } + if (node.next != null) { + node.next.previous = node.previous; + } else { + this.tail = node.previous; + } + if (node.previousSibling == null && node.nextSibling == null) { + KeyList keyList = this.keyToKeyList.remove(node.key); + keyList.count = 0; + ++this.modCount; + } else { + KeyList keyList = this.keyToKeyList.get(node.key); + --keyList.count; + if (node.previousSibling == null) { + keyList.head = node.nextSibling; + } else { + node.previousSibling.nextSibling = node.nextSibling; + } + if (node.nextSibling == null) { + keyList.tail = node.previousSibling; + } else { + node.nextSibling.previousSibling = node.previousSibling; + } + } + --this.size; + } + + private void removeAllNodes(@Nullable Object key) { + Iterators.clear(new ValueForKeyIterator(key)); + } + + private static void checkElement(@Nullable Object node) { + if (node == null) { + throw new NoSuchElementException(); + } + } + + @Override + public int size() { + return this.size; + } + + @Override + public boolean isEmpty() { + return this.head == null; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.keyToKeyList.containsKey(key); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.values().contains(value); + } + + @Override + public boolean put(@Nullable K key, @Nullable V value) { + this.addNode(key, value, null); + return true; + } + + @Override + public List replaceValues(@Nullable K key, Iterable values) { + List oldValues = this.getCopy(key); + ValueForKeyIterator keyValues = new ValueForKeyIterator(key); + Iterator newValues = values.iterator(); + while (keyValues.hasNext() && newValues.hasNext()) { + keyValues.next(); + keyValues.set(newValues.next()); + } + while (keyValues.hasNext()) { + keyValues.next(); + keyValues.remove(); + } + while (newValues.hasNext()) { + keyValues.add(newValues.next()); + } + return oldValues; + } + + private List getCopy(@Nullable Object key) { + return Collections.unmodifiableList(Lists.newArrayList(new ValueForKeyIterator(key))); + } + + @Override + public List removeAll(@Nullable Object key) { + List oldValues = this.getCopy(key); + this.removeAllNodes(key); + return oldValues; + } + + @Override + public void clear() { + this.head = null; + this.tail = null; + this.keyToKeyList.clear(); + this.size = 0; + ++this.modCount; + } + + @Override + public List get(final @Nullable K key) { + return new AbstractSequentialList(){ + + @Override + public int size() { + KeyList keyList = (KeyList)LinkedListMultimap.this.keyToKeyList.get(key); + return keyList == null ? 0 : keyList.count; + } + + @Override + public ListIterator listIterator(int index) { + return new ValueForKeyIterator(key, index); + } + }; + } + + @Override + Set createKeySet() { + return new Sets.ImprovedAbstractSet(){ + + @Override + public int size() { + return LinkedListMultimap.this.keyToKeyList.size(); + } + + @Override + public Iterator iterator() { + return new DistinctKeyIterator(); + } + + @Override + public boolean contains(Object key) { + return LinkedListMultimap.this.containsKey(key); + } + + @Override + public boolean remove(Object o) { + return !LinkedListMultimap.this.removeAll(o).isEmpty(); + } + }; + } + + @Override + public List values() { + return (List)super.values(); + } + + @Override + List createValues() { + return new AbstractSequentialList(){ + + @Override + public int size() { + return LinkedListMultimap.this.size; + } + + @Override + public ListIterator listIterator(int index) { + final NodeIterator nodeItr = new NodeIterator(index); + return new TransformedListIterator, V>(nodeItr){ + + @Override + V transform(Map.Entry entry) { + return entry.getValue(); + } + + @Override + public void set(V value) { + nodeItr.setValue(value); + } + }; + } + }; + } + + @Override + public List> entries() { + return (List)super.entries(); + } + + @Override + List> createEntries() { + return new AbstractSequentialList>(){ + + @Override + public int size() { + return LinkedListMultimap.this.size; + } + + @Override + public ListIterator> listIterator(int index) { + return new NodeIterator(index); + } + }; + } + + @Override + Iterator> entryIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + Map> createAsMap() { + return new Multimaps.AsMap(this); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeInt(this.size()); + for (Map.Entry entry : this.entries()) { + stream.writeObject(entry.getKey()); + stream.writeObject(entry.getValue()); + } + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.keyToKeyList = Maps.newLinkedHashMap(); + int size = stream.readInt(); + for (int i = 0; i < size; ++i) { + Object key = stream.readObject(); + Object value = stream.readObject(); + this.put(key, value); + } + } + + private class ValueForKeyIterator + implements ListIterator { + final Object key; + int nextIndex; + Node next; + Node current; + Node previous; + + ValueForKeyIterator(Object key) { + this.key = key; + KeyList keyList = (KeyList)LinkedListMultimap.this.keyToKeyList.get(key); + this.next = keyList == null ? null : keyList.head; + } + + public ValueForKeyIterator(Object key, int index) { + KeyList keyList = (KeyList)LinkedListMultimap.this.keyToKeyList.get(key); + int size = keyList == null ? 0 : keyList.count; + Preconditions.checkPositionIndex(index, size); + if (index >= size / 2) { + this.previous = keyList == null ? null : keyList.tail; + this.nextIndex = size; + while (index++ < size) { + this.previous(); + } + } else { + Node node = this.next = keyList == null ? null : keyList.head; + while (index-- > 0) { + this.next(); + } + } + this.key = key; + this.current = null; + } + + @Override + public boolean hasNext() { + return this.next != null; + } + + @Override + public V next() { + LinkedListMultimap.checkElement(this.next); + this.current = this.next; + this.previous = this.current; + this.next = this.next.nextSibling; + ++this.nextIndex; + return this.current.value; + } + + @Override + public boolean hasPrevious() { + return this.previous != null; + } + + @Override + public V previous() { + LinkedListMultimap.checkElement(this.previous); + this.current = this.previous; + this.next = this.current; + this.previous = this.previous.previousSibling; + --this.nextIndex; + return this.current.value; + } + + @Override + public int nextIndex() { + return this.nextIndex; + } + + @Override + public int previousIndex() { + return this.nextIndex - 1; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.current != null); + if (this.current != this.next) { + this.previous = this.current.previousSibling; + --this.nextIndex; + } else { + this.next = this.current.nextSibling; + } + LinkedListMultimap.this.removeNode(this.current); + this.current = null; + } + + @Override + public void set(V value) { + Preconditions.checkState(this.current != null); + this.current.value = value; + } + + @Override + public void add(V value) { + this.previous = LinkedListMultimap.this.addNode(this.key, value, this.next); + ++this.nextIndex; + this.current = null; + } + } + + private class DistinctKeyIterator + implements Iterator { + final Set seenKeys; + Node next; + Node current; + int expectedModCount; + + private DistinctKeyIterator() { + this.seenKeys = Sets.newHashSetWithExpectedSize(LinkedListMultimap.this.keySet().size()); + this.next = LinkedListMultimap.this.head; + this.expectedModCount = LinkedListMultimap.this.modCount; + } + + private void checkForConcurrentModification() { + if (LinkedListMultimap.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + @Override + public boolean hasNext() { + this.checkForConcurrentModification(); + return this.next != null; + } + + @Override + public K next() { + this.checkForConcurrentModification(); + LinkedListMultimap.checkElement(this.next); + this.current = this.next; + this.seenKeys.add(this.current.key); + do { + this.next = this.next.next; + } while (this.next != null && !this.seenKeys.add(this.next.key)); + return this.current.key; + } + + @Override + public void remove() { + this.checkForConcurrentModification(); + CollectPreconditions.checkRemove(this.current != null); + LinkedListMultimap.this.removeAllNodes(this.current.key); + this.current = null; + this.expectedModCount = LinkedListMultimap.this.modCount; + } + } + + private class NodeIterator + implements ListIterator> { + int nextIndex; + Node next; + Node current; + Node previous; + int expectedModCount; + + NodeIterator(int index) { + this.expectedModCount = LinkedListMultimap.this.modCount; + int size = LinkedListMultimap.this.size(); + Preconditions.checkPositionIndex(index, size); + if (index >= size / 2) { + this.previous = LinkedListMultimap.this.tail; + this.nextIndex = size; + while (index++ < size) { + this.previous(); + } + } else { + this.next = LinkedListMultimap.this.head; + while (index-- > 0) { + this.next(); + } + } + this.current = null; + } + + private void checkForConcurrentModification() { + if (LinkedListMultimap.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + @Override + public boolean hasNext() { + this.checkForConcurrentModification(); + return this.next != null; + } + + @Override + public Node next() { + this.checkForConcurrentModification(); + LinkedListMultimap.checkElement(this.next); + this.current = this.next; + this.previous = this.current; + this.next = this.next.next; + ++this.nextIndex; + return this.current; + } + + @Override + public void remove() { + this.checkForConcurrentModification(); + CollectPreconditions.checkRemove(this.current != null); + if (this.current != this.next) { + this.previous = this.current.previous; + --this.nextIndex; + } else { + this.next = this.current.next; + } + LinkedListMultimap.this.removeNode(this.current); + this.current = null; + this.expectedModCount = LinkedListMultimap.this.modCount; + } + + @Override + public boolean hasPrevious() { + this.checkForConcurrentModification(); + return this.previous != null; + } + + @Override + public Node previous() { + this.checkForConcurrentModification(); + LinkedListMultimap.checkElement(this.previous); + this.current = this.previous; + this.next = this.current; + this.previous = this.previous.previous; + --this.nextIndex; + return this.current; + } + + @Override + public int nextIndex() { + return this.nextIndex; + } + + @Override + public int previousIndex() { + return this.nextIndex - 1; + } + + @Override + public void set(Map.Entry e) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(Map.Entry e) { + throw new UnsupportedOperationException(); + } + + void setValue(V value) { + Preconditions.checkState(this.current != null); + this.current.value = value; + } + } + + private static class KeyList { + Node head; + Node tail; + int count; + + KeyList(Node firstNode) { + this.head = firstNode; + this.tail = firstNode; + firstNode.previousSibling = null; + firstNode.nextSibling = null; + this.count = 1; + } + } + + private static final class Node + extends AbstractMapEntry { + final K key; + V value; + Node next; + Node previous; + Node nextSibling; + Node previousSibling; + + Node(@Nullable K key, @Nullable V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public V getValue() { + return this.value; + } + + @Override + public V setValue(@Nullable V newValue) { + V result = this.value; + this.value = newValue; + return result; + } + } +} diff --git a/src/com/google/common/collect/ListMultimap.java b/src/com/google/common/collect/ListMultimap.java new file mode 100644 index 0000000..256bf1d --- /dev/null +++ b/src/com/google/common/collect/ListMultimap.java @@ -0,0 +1,30 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public interface ListMultimap +extends Multimap { + @Override + public List get(@Nullable K var1); + + @Override + public List removeAll(@Nullable Object var1); + + @Override + public List replaceValues(K var1, Iterable var2); + + @Override + public Map> asMap(); + + @Override + public boolean equals(@Nullable Object var1); +} diff --git a/src/com/google/common/collect/Lists.java b/src/com/google/common/collect/Lists.java new file mode 100644 index 0000000..a30697a --- /dev/null +++ b/src/com/google/common/collect/Lists.java @@ -0,0 +1,679 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.CartesianList; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.TransformedListIterator; +import com.google.common.math.IntMath; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.math.RoundingMode; +import java.util.AbstractList; +import java.util.AbstractSequentialList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.RandomAccess; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Lists { + private Lists() { + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList() { + return new ArrayList(); + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(E ... elements) { + Preconditions.checkNotNull(elements); + int capacity = Lists.computeArrayListCapacity(elements.length); + ArrayList list = new ArrayList(capacity); + Collections.addAll(list, elements); + return list; + } + + @VisibleForTesting + static int computeArrayListCapacity(int arraySize) { + CollectPreconditions.checkNonnegative(arraySize, "arraySize"); + return Ints.saturatedCast(5L + (long)arraySize + (long)(arraySize / 10)); + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(Iterable elements) { + Preconditions.checkNotNull(elements); + return elements instanceof Collection ? new ArrayList(Collections2.cast(elements)) : Lists.newArrayList(elements.iterator()); + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(Iterator elements) { + ArrayList list = Lists.newArrayList(); + Iterators.addAll(list, elements); + return list; + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayListWithCapacity(int initialArraySize) { + CollectPreconditions.checkNonnegative(initialArraySize, "initialArraySize"); + return new ArrayList(initialArraySize); + } + + @GwtCompatible(serializable=true) + public static ArrayList newArrayListWithExpectedSize(int estimatedSize) { + return new ArrayList(Lists.computeArrayListCapacity(estimatedSize)); + } + + @GwtCompatible(serializable=true) + public static LinkedList newLinkedList() { + return new LinkedList(); + } + + @GwtCompatible(serializable=true) + public static LinkedList newLinkedList(Iterable elements) { + LinkedList list = Lists.newLinkedList(); + Iterables.addAll(list, elements); + return list; + } + + @GwtIncompatible(value="CopyOnWriteArrayList") + public static CopyOnWriteArrayList newCopyOnWriteArrayList() { + return new CopyOnWriteArrayList(); + } + + @GwtIncompatible(value="CopyOnWriteArrayList") + public static CopyOnWriteArrayList newCopyOnWriteArrayList(Iterable elements) { + Collection elementsCollection = elements instanceof Collection ? Collections2.cast(elements) : Lists.newArrayList(elements); + return new CopyOnWriteArrayList(elementsCollection); + } + + public static List asList(@Nullable E first, E[] rest) { + return new OnePlusArrayList(first, rest); + } + + public static List asList(@Nullable E first, @Nullable E second, E[] rest) { + return new TwoPlusArrayList(first, second, rest); + } + + static List> cartesianProduct(List> lists) { + return CartesianList.create(lists); + } + + static List> cartesianProduct(List ... lists) { + return Lists.cartesianProduct(Arrays.asList(lists)); + } + + public static List transform(List fromList, Function function) { + return fromList instanceof RandomAccess ? new TransformingRandomAccessList(fromList, function) : new TransformingSequentialList(fromList, function); + } + + public static List> partition(List list, int size) { + Preconditions.checkNotNull(list); + Preconditions.checkArgument(size > 0); + return list instanceof RandomAccess ? new RandomAccessPartition(list, size) : new Partition(list, size); + } + + @Beta + public static ImmutableList charactersOf(String string) { + return new StringAsImmutableList(Preconditions.checkNotNull(string)); + } + + @Beta + public static List charactersOf(CharSequence sequence) { + return new CharSequenceAsList(Preconditions.checkNotNull(sequence)); + } + + public static List reverse(List list) { + if (list instanceof ImmutableList) { + return ((ImmutableList)list).reverse(); + } + if (list instanceof ReverseList) { + return ((ReverseList)list).getForwardList(); + } + if (list instanceof RandomAccess) { + return new RandomAccessReverseList(list); + } + return new ReverseList(list); + } + + static int hashCodeImpl(List list) { + int hashCode = 1; + for (Object o : list) { + hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode()); + hashCode = ~(~hashCode); + } + return hashCode; + } + + static boolean equalsImpl(List list, @Nullable Object object) { + if (object == Preconditions.checkNotNull(list)) { + return true; + } + if (!(object instanceof List)) { + return false; + } + List o = (List)object; + return list.size() == o.size() && Iterators.elementsEqual(list.iterator(), o.iterator()); + } + + static boolean addAllImpl(List list, int index, Iterable elements) { + boolean changed = false; + ListIterator listIterator = list.listIterator(index); + for (E e : elements) { + listIterator.add(e); + changed = true; + } + return changed; + } + + static int indexOfImpl(List list, @Nullable Object element) { + ListIterator listIterator = list.listIterator(); + while (listIterator.hasNext()) { + if (!Objects.equal(element, listIterator.next())) continue; + return listIterator.previousIndex(); + } + return -1; + } + + static int lastIndexOfImpl(List list, @Nullable Object element) { + ListIterator listIterator = list.listIterator(list.size()); + while (listIterator.hasPrevious()) { + if (!Objects.equal(element, listIterator.previous())) continue; + return listIterator.nextIndex(); + } + return -1; + } + + static ListIterator listIteratorImpl(List list, int index) { + return new AbstractListWrapper(list).listIterator(index); + } + + static List subListImpl(List list, int fromIndex, int toIndex) { + AbstractListWrapper wrapper = list instanceof RandomAccess ? new RandomAccessListWrapper((List)list){ + private static final long serialVersionUID = 0L; + + @Override + public ListIterator listIterator(int index) { + return this.backingList.listIterator(index); + } + } : new AbstractListWrapper((List)list){ + private static final long serialVersionUID = 0L; + + @Override + public ListIterator listIterator(int index) { + return this.backingList.listIterator(index); + } + }; + return wrapper.subList(fromIndex, toIndex); + } + + static List cast(Iterable iterable) { + return (List)iterable; + } + + private static class RandomAccessListWrapper + extends AbstractListWrapper + implements RandomAccess { + RandomAccessListWrapper(List backingList) { + super(backingList); + } + } + + private static class AbstractListWrapper + extends AbstractList { + final List backingList; + + AbstractListWrapper(List backingList) { + this.backingList = Preconditions.checkNotNull(backingList); + } + + @Override + public void add(int index, E element) { + this.backingList.add(index, element); + } + + @Override + public boolean addAll(int index, Collection c) { + return this.backingList.addAll(index, c); + } + + @Override + public E get(int index) { + return this.backingList.get(index); + } + + @Override + public E remove(int index) { + return this.backingList.remove(index); + } + + @Override + public E set(int index, E element) { + return this.backingList.set(index, element); + } + + @Override + public boolean contains(Object o) { + return this.backingList.contains(o); + } + + @Override + public int size() { + return this.backingList.size(); + } + } + + private static class RandomAccessReverseList + extends ReverseList + implements RandomAccess { + RandomAccessReverseList(List forwardList) { + super(forwardList); + } + } + + private static class ReverseList + extends AbstractList { + private final List forwardList; + + ReverseList(List forwardList) { + this.forwardList = Preconditions.checkNotNull(forwardList); + } + + List getForwardList() { + return this.forwardList; + } + + private int reverseIndex(int index) { + int size = this.size(); + Preconditions.checkElementIndex(index, size); + return size - 1 - index; + } + + private int reversePosition(int index) { + int size = this.size(); + Preconditions.checkPositionIndex(index, size); + return size - index; + } + + @Override + public void add(int index, @Nullable T element) { + this.forwardList.add(this.reversePosition(index), element); + } + + @Override + public void clear() { + this.forwardList.clear(); + } + + @Override + public T remove(int index) { + return this.forwardList.remove(this.reverseIndex(index)); + } + + @Override + protected void removeRange(int fromIndex, int toIndex) { + this.subList(fromIndex, toIndex).clear(); + } + + @Override + public T set(int index, @Nullable T element) { + return this.forwardList.set(this.reverseIndex(index), element); + } + + @Override + public T get(int index) { + return this.forwardList.get(this.reverseIndex(index)); + } + + @Override + public int size() { + return this.forwardList.size(); + } + + @Override + public List subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size()); + return Lists.reverse(this.forwardList.subList(this.reversePosition(toIndex), this.reversePosition(fromIndex))); + } + + @Override + public Iterator iterator() { + return this.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + int start = this.reversePosition(index); + final ListIterator forwardIterator = this.forwardList.listIterator(start); + return new ListIterator(){ + boolean canRemoveOrSet; + + @Override + public void add(T e) { + forwardIterator.add(e); + forwardIterator.previous(); + this.canRemoveOrSet = false; + } + + @Override + public boolean hasNext() { + return forwardIterator.hasPrevious(); + } + + @Override + public boolean hasPrevious() { + return forwardIterator.hasNext(); + } + + @Override + public T next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.canRemoveOrSet = true; + return forwardIterator.previous(); + } + + @Override + public int nextIndex() { + return ReverseList.this.reversePosition(forwardIterator.nextIndex()); + } + + @Override + public T previous() { + if (!this.hasPrevious()) { + throw new NoSuchElementException(); + } + this.canRemoveOrSet = true; + return forwardIterator.next(); + } + + @Override + public int previousIndex() { + return this.nextIndex() - 1; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.canRemoveOrSet); + forwardIterator.remove(); + this.canRemoveOrSet = false; + } + + @Override + public void set(T e) { + Preconditions.checkState(this.canRemoveOrSet); + forwardIterator.set(e); + } + }; + } + } + + private static final class CharSequenceAsList + extends AbstractList { + private final CharSequence sequence; + + CharSequenceAsList(CharSequence sequence) { + this.sequence = sequence; + } + + @Override + public Character get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return Character.valueOf(this.sequence.charAt(index)); + } + + @Override + public int size() { + return this.sequence.length(); + } + } + + private static final class StringAsImmutableList + extends ImmutableList { + private final String string; + + StringAsImmutableList(String string) { + this.string = string; + } + + @Override + public int indexOf(@Nullable Object object) { + return object instanceof Character ? this.string.indexOf(((Character)object).charValue()) : -1; + } + + @Override + public int lastIndexOf(@Nullable Object object) { + return object instanceof Character ? this.string.lastIndexOf(((Character)object).charValue()) : -1; + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size()); + return Lists.charactersOf(this.string.substring(fromIndex, toIndex)); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public Character get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return Character.valueOf(this.string.charAt(index)); + } + + @Override + public int size() { + return this.string.length(); + } + } + + private static class RandomAccessPartition + extends Partition + implements RandomAccess { + RandomAccessPartition(List list, int size) { + super(list, size); + } + } + + private static class Partition + extends AbstractList> { + final List list; + final int size; + + Partition(List list, int size) { + this.list = list; + this.size = size; + } + + @Override + public List get(int index) { + Preconditions.checkElementIndex(index, this.size()); + int start = index * this.size; + int end = Math.min(start + this.size, this.list.size()); + return this.list.subList(start, end); + } + + @Override + public int size() { + return IntMath.divide(this.list.size(), this.size, RoundingMode.CEILING); + } + + @Override + public boolean isEmpty() { + return this.list.isEmpty(); + } + } + + private static class TransformingRandomAccessList + extends AbstractList + implements RandomAccess, + Serializable { + final List fromList; + final Function function; + private static final long serialVersionUID = 0L; + + TransformingRandomAccessList(List fromList, Function function) { + this.fromList = Preconditions.checkNotNull(fromList); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public void clear() { + this.fromList.clear(); + } + + @Override + public T get(int index) { + return this.function.apply(this.fromList.get(index)); + } + + @Override + public Iterator iterator() { + return this.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return new TransformedListIterator(this.fromList.listIterator(index)){ + + @Override + T transform(F from) { + return TransformingRandomAccessList.this.function.apply(from); + } + }; + } + + @Override + public boolean isEmpty() { + return this.fromList.isEmpty(); + } + + @Override + public T remove(int index) { + return this.function.apply(this.fromList.remove(index)); + } + + @Override + public int size() { + return this.fromList.size(); + } + } + + private static class TransformingSequentialList + extends AbstractSequentialList + implements Serializable { + final List fromList; + final Function function; + private static final long serialVersionUID = 0L; + + TransformingSequentialList(List fromList, Function function) { + this.fromList = Preconditions.checkNotNull(fromList); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public void clear() { + this.fromList.clear(); + } + + @Override + public int size() { + return this.fromList.size(); + } + + @Override + public ListIterator listIterator(int index) { + return new TransformedListIterator(this.fromList.listIterator(index)){ + + @Override + T transform(F from) { + return TransformingSequentialList.this.function.apply(from); + } + }; + } + } + + private static class TwoPlusArrayList + extends AbstractList + implements Serializable, + RandomAccess { + final E first; + final E second; + final E[] rest; + private static final long serialVersionUID = 0L; + + TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) { + this.first = first; + this.second = second; + this.rest = Preconditions.checkNotNull(rest); + } + + @Override + public int size() { + return this.rest.length + 2; + } + + @Override + public E get(int index) { + switch (index) { + case 0: { + return this.first; + } + case 1: { + return this.second; + } + } + Preconditions.checkElementIndex(index, this.size()); + return this.rest[index - 2]; + } + } + + private static class OnePlusArrayList + extends AbstractList + implements Serializable, + RandomAccess { + final E first; + final E[] rest; + private static final long serialVersionUID = 0L; + + OnePlusArrayList(@Nullable E first, E[] rest) { + this.first = first; + this.rest = Preconditions.checkNotNull(rest); + } + + @Override + public int size() { + return this.rest.length + 1; + } + + @Override + public E get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return index == 0 ? this.first : this.rest[index - 1]; + } + } +} diff --git a/src/com/google/common/collect/MapConstraint.java b/src/com/google/common/collect/MapConstraint.java new file mode 100644 index 0000000..86c4cb8 --- /dev/null +++ b/src/com/google/common/collect/MapConstraint.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +@Beta +public interface MapConstraint { + public void checkKeyValue(@Nullable K var1, @Nullable V var2); + + public String toString(); +} diff --git a/src/com/google/common/collect/MapConstraints.java b/src/com/google/common/collect/MapConstraints.java new file mode 100644 index 0000000..7bc4779 --- /dev/null +++ b/src/com/google/common/collect/MapConstraints.java @@ -0,0 +1,680 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.Constraint; +import com.google.common.collect.Constraints; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingIterator; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ForwardingMultimap; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.MapConstraint; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedSetMultimap; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class MapConstraints { + private MapConstraints() { + } + + public static MapConstraint notNull() { + return NotNullMapConstraint.INSTANCE; + } + + public static Map constrainedMap(Map map, MapConstraint constraint) { + return new ConstrainedMap(map, constraint); + } + + public static Multimap constrainedMultimap(Multimap multimap, MapConstraint constraint) { + return new ConstrainedMultimap(multimap, constraint); + } + + public static ListMultimap constrainedListMultimap(ListMultimap multimap, MapConstraint constraint) { + return new ConstrainedListMultimap(multimap, constraint); + } + + public static SetMultimap constrainedSetMultimap(SetMultimap multimap, MapConstraint constraint) { + return new ConstrainedSetMultimap(multimap, constraint); + } + + public static SortedSetMultimap constrainedSortedSetMultimap(SortedSetMultimap multimap, MapConstraint constraint) { + return new ConstrainedSortedSetMultimap(multimap, constraint); + } + + private static Map.Entry constrainedEntry(final Map.Entry entry, final MapConstraint constraint) { + Preconditions.checkNotNull(entry); + Preconditions.checkNotNull(constraint); + return new ForwardingMapEntry(){ + + @Override + protected Map.Entry delegate() { + return entry; + } + + @Override + public V setValue(V value) { + constraint.checkKeyValue(this.getKey(), value); + return entry.setValue(value); + } + }; + } + + private static Map.Entry> constrainedAsMapEntry(final Map.Entry> entry, final MapConstraint constraint) { + Preconditions.checkNotNull(entry); + Preconditions.checkNotNull(constraint); + return new ForwardingMapEntry>(){ + + @Override + protected Map.Entry> delegate() { + return entry; + } + + @Override + public Collection getValue() { + return Constraints.constrainedTypePreservingCollection((Collection)entry.getValue(), new Constraint(){ + + @Override + public V checkElement(V value) { + constraint.checkKeyValue(this.getKey(), value); + return value; + } + }); + } + }; + } + + private static Set>> constrainedAsMapEntries(Set>> entries, MapConstraint constraint) { + return new ConstrainedAsMapEntries(entries, constraint); + } + + private static Collection> constrainedEntries(Collection> entries, MapConstraint constraint) { + if (entries instanceof Set) { + return MapConstraints.constrainedEntrySet((Set)entries, constraint); + } + return new ConstrainedEntries(entries, constraint); + } + + private static Set> constrainedEntrySet(Set> entries, MapConstraint constraint) { + return new ConstrainedEntrySet(entries, constraint); + } + + public static BiMap constrainedBiMap(BiMap map, MapConstraint constraint) { + return new ConstrainedBiMap(map, null, constraint); + } + + private static Collection checkValues(K key, Iterable values, MapConstraint constraint) { + ArrayList copy = Lists.newArrayList(values); + for (Object value : copy) { + constraint.checkKeyValue(key, value); + } + return copy; + } + + private static Map checkMap(Map map, MapConstraint constraint) { + LinkedHashMap copy = new LinkedHashMap(map); + for (Map.Entry entry : copy.entrySet()) { + constraint.checkKeyValue(entry.getKey(), entry.getValue()); + } + return copy; + } + + private static class ConstrainedSortedSetMultimap + extends ConstrainedSetMultimap + implements SortedSetMultimap { + ConstrainedSortedSetMultimap(SortedSetMultimap delegate, MapConstraint constraint) { + super(delegate, constraint); + } + + @Override + public SortedSet get(K key) { + return (SortedSet)super.get((Object)key); + } + + @Override + public SortedSet removeAll(Object key) { + return (SortedSet)super.removeAll(key); + } + + @Override + public SortedSet replaceValues(K key, Iterable values) { + return (SortedSet)super.replaceValues((Object)key, (Iterable)values); + } + + @Override + public Comparator valueComparator() { + return ((SortedSetMultimap)this.delegate()).valueComparator(); + } + } + + private static class ConstrainedSetMultimap + extends ConstrainedMultimap + implements SetMultimap { + ConstrainedSetMultimap(SetMultimap delegate, MapConstraint constraint) { + super(delegate, constraint); + } + + @Override + public Set get(K key) { + return (Set)super.get(key); + } + + @Override + public Set> entries() { + return (Set)super.entries(); + } + + @Override + public Set removeAll(Object key) { + return (Set)super.removeAll(key); + } + + @Override + public Set replaceValues(K key, Iterable values) { + return (Set)super.replaceValues(key, values); + } + } + + private static class ConstrainedListMultimap + extends ConstrainedMultimap + implements ListMultimap { + ConstrainedListMultimap(ListMultimap delegate, MapConstraint constraint) { + super(delegate, constraint); + } + + @Override + public List get(K key) { + return (List)super.get(key); + } + + @Override + public List removeAll(Object key) { + return (List)super.removeAll(key); + } + + @Override + public List replaceValues(K key, Iterable values) { + return (List)super.replaceValues(key, values); + } + } + + static class ConstrainedAsMapEntries + extends ForwardingSet>> { + private final MapConstraint constraint; + private final Set>> entries; + + ConstrainedAsMapEntries(Set>> entries, MapConstraint constraint) { + this.entries = entries; + this.constraint = constraint; + } + + @Override + protected Set>> delegate() { + return this.entries; + } + + @Override + public Iterator>> iterator() { + final Iterator>> iterator = this.entries.iterator(); + return new ForwardingIterator>>(){ + + @Override + public Map.Entry> next() { + return MapConstraints.constrainedAsMapEntry((Map.Entry)iterator.next(), ConstrainedAsMapEntries.this.constraint); + } + + @Override + protected Iterator>> delegate() { + return iterator; + } + }; + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public boolean contains(Object o) { + return Maps.containsEntryImpl(this.delegate(), o); + } + + @Override + public boolean containsAll(Collection c) { + return this.standardContainsAll(c); + } + + @Override + public boolean equals(@Nullable Object object) { + return this.standardEquals(object); + } + + @Override + public int hashCode() { + return this.standardHashCode(); + } + + @Override + public boolean remove(Object o) { + return Maps.removeEntryImpl(this.delegate(), o); + } + + @Override + public boolean removeAll(Collection c) { + return this.standardRemoveAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return this.standardRetainAll(c); + } + } + + static class ConstrainedEntrySet + extends ConstrainedEntries + implements Set> { + ConstrainedEntrySet(Set> entries, MapConstraint constraint) { + super(entries, constraint); + } + + @Override + public boolean equals(@Nullable Object object) { + return Sets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + private static class ConstrainedEntries + extends ForwardingCollection> { + final MapConstraint constraint; + final Collection> entries; + + ConstrainedEntries(Collection> entries, MapConstraint constraint) { + this.entries = entries; + this.constraint = constraint; + } + + @Override + protected Collection> delegate() { + return this.entries; + } + + @Override + public Iterator> iterator() { + final Iterator> iterator = this.entries.iterator(); + return new ForwardingIterator>(){ + + @Override + public Map.Entry next() { + return MapConstraints.constrainedEntry((Map.Entry)iterator.next(), ConstrainedEntries.this.constraint); + } + + @Override + protected Iterator> delegate() { + return iterator; + } + }; + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public boolean contains(Object o) { + return Maps.containsEntryImpl(this.delegate(), o); + } + + @Override + public boolean containsAll(Collection c) { + return this.standardContainsAll(c); + } + + @Override + public boolean remove(Object o) { + return Maps.removeEntryImpl(this.delegate(), o); + } + + @Override + public boolean removeAll(Collection c) { + return this.standardRemoveAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return this.standardRetainAll(c); + } + } + + private static class ConstrainedAsMapValues + extends ForwardingCollection> { + final Collection> delegate; + final Set>> entrySet; + + ConstrainedAsMapValues(Collection> delegate, Set>> entrySet) { + this.delegate = delegate; + this.entrySet = entrySet; + } + + @Override + protected Collection> delegate() { + return this.delegate; + } + + @Override + public Iterator> iterator() { + final Iterator>> iterator = this.entrySet.iterator(); + return new Iterator>(){ + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Collection next() { + return (Collection)((Map.Entry)iterator.next()).getValue(); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public boolean contains(Object o) { + return this.standardContains(o); + } + + @Override + public boolean containsAll(Collection c) { + return this.standardContainsAll(c); + } + + @Override + public boolean remove(Object o) { + return this.standardRemove(o); + } + + @Override + public boolean removeAll(Collection c) { + return this.standardRemoveAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return this.standardRetainAll(c); + } + } + + private static class ConstrainedMultimap + extends ForwardingMultimap + implements Serializable { + final MapConstraint constraint; + final Multimap delegate; + transient Collection> entries; + transient Map> asMap; + + public ConstrainedMultimap(Multimap delegate, MapConstraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected Multimap delegate() { + return this.delegate; + } + + @Override + public Map> asMap() { + ForwardingMap result = this.asMap; + if (result == null) { + final Map> asMapDelegate = this.delegate.asMap(); + this.asMap = result = new ForwardingMap>(){ + Set>> entrySet; + Collection> values; + + @Override + protected Map> delegate() { + return asMapDelegate; + } + + @Override + public Set>> entrySet() { + Set result = this.entrySet; + if (result == null) { + this.entrySet = result = MapConstraints.constrainedAsMapEntries(asMapDelegate.entrySet(), ConstrainedMultimap.this.constraint); + } + return result; + } + + @Override + public Collection get(Object key) { + try { + Collection collection = ConstrainedMultimap.this.get(key); + return collection.isEmpty() ? null : collection; + } + catch (ClassCastException e) { + return null; + } + } + + @Override + public Collection> values() { + Collection result = this.values; + if (result == null) { + this.values = result = new ConstrainedAsMapValues(this.delegate().values(), this.entrySet()); + } + return result; + } + + @Override + public boolean containsValue(Object o) { + return this.values().contains(o); + } + }; + } + return result; + } + + @Override + public Collection> entries() { + Collection result = this.entries; + if (result == null) { + this.entries = result = MapConstraints.constrainedEntries(this.delegate.entries(), this.constraint); + } + return result; + } + + @Override + public Collection get(final K key) { + return Constraints.constrainedTypePreservingCollection(this.delegate.get(key), new Constraint(){ + + @Override + public V checkElement(V value) { + ConstrainedMultimap.this.constraint.checkKeyValue(key, value); + return value; + } + }); + } + + @Override + public boolean put(K key, V value) { + this.constraint.checkKeyValue(key, value); + return this.delegate.put(key, value); + } + + @Override + public boolean putAll(K key, Iterable values) { + return this.delegate.putAll(key, MapConstraints.checkValues(key, values, this.constraint)); + } + + @Override + public boolean putAll(Multimap multimap) { + boolean changed = false; + for (Map.Entry entry : multimap.entries()) { + changed |= this.put(entry.getKey(), entry.getValue()); + } + return changed; + } + + @Override + public Collection replaceValues(K key, Iterable values) { + return this.delegate.replaceValues(key, MapConstraints.checkValues(key, values, this.constraint)); + } + } + + private static class InverseConstraint + implements MapConstraint { + final MapConstraint constraint; + + public InverseConstraint(MapConstraint constraint) { + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + public void checkKeyValue(K key, V value) { + this.constraint.checkKeyValue(value, key); + } + } + + private static class ConstrainedBiMap + extends ConstrainedMap + implements BiMap { + volatile BiMap inverse; + + ConstrainedBiMap(BiMap delegate, @Nullable BiMap inverse, MapConstraint constraint) { + super(delegate, constraint); + this.inverse = inverse; + } + + @Override + protected BiMap delegate() { + return (BiMap)super.delegate(); + } + + @Override + public V forcePut(K key, V value) { + this.constraint.checkKeyValue(key, value); + return this.delegate().forcePut(key, value); + } + + @Override + public BiMap inverse() { + if (this.inverse == null) { + this.inverse = new ConstrainedBiMap(this.delegate().inverse(), this, new InverseConstraint(this.constraint)); + } + return this.inverse; + } + + @Override + public Set values() { + return this.delegate().values(); + } + } + + static class ConstrainedMap + extends ForwardingMap { + private final Map delegate; + final MapConstraint constraint; + private transient Set> entrySet; + + ConstrainedMap(Map delegate, MapConstraint constraint) { + this.delegate = Preconditions.checkNotNull(delegate); + this.constraint = Preconditions.checkNotNull(constraint); + } + + @Override + protected Map delegate() { + return this.delegate; + } + + @Override + public Set> entrySet() { + Set result = this.entrySet; + if (result == null) { + this.entrySet = result = MapConstraints.constrainedEntrySet(this.delegate.entrySet(), this.constraint); + } + return result; + } + + @Override + public V put(K key, V value) { + this.constraint.checkKeyValue(key, value); + return this.delegate.put(key, value); + } + + @Override + public void putAll(Map map) { + this.delegate.putAll(MapConstraints.checkMap(map, this.constraint)); + } + } + + private static enum NotNullMapConstraint implements MapConstraint + { + INSTANCE; + + + @Override + public void checkKeyValue(Object key, Object value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + } + + @Override + public String toString() { + return "Not null"; + } + } +} diff --git a/src/com/google/common/collect/MapDifference.java b/src/com/google/common/collect/MapDifference.java new file mode 100644 index 0000000..1e9cec4 --- /dev/null +++ b/src/com/google/common/collect/MapDifference.java @@ -0,0 +1,35 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public interface MapDifference { + public boolean areEqual(); + + public Map entriesOnlyOnLeft(); + + public Map entriesOnlyOnRight(); + + public Map entriesInCommon(); + + public Map> entriesDiffering(); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + + public static interface ValueDifference { + public V leftValue(); + + public V rightValue(); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + } +} diff --git a/src/com/google/common/collect/MapMaker.java b/src/com/google/common/collect/MapMaker.java new file mode 100644 index 0000000..11f7b51 --- /dev/null +++ b/src/com/google/common/collect/MapMaker.java @@ -0,0 +1,450 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.base.Ticker; +import com.google.common.collect.ComputationException; +import com.google.common.collect.ComputingConcurrentHashMap; +import com.google.common.collect.GenericMapMaker; +import com.google.common.collect.ImmutableEntry; +import com.google.common.collect.MapMakerInternalMap; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class MapMaker +extends GenericMapMaker { + private static final int DEFAULT_INITIAL_CAPACITY = 16; + private static final int DEFAULT_CONCURRENCY_LEVEL = 4; + private static final int DEFAULT_EXPIRATION_NANOS = 0; + static final int UNSET_INT = -1; + boolean useCustomMap; + int initialCapacity = -1; + int concurrencyLevel = -1; + int maximumSize = -1; + MapMakerInternalMap.Strength keyStrength; + MapMakerInternalMap.Strength valueStrength; + long expireAfterWriteNanos = -1L; + long expireAfterAccessNanos = -1L; + RemovalCause nullRemovalCause; + Equivalence keyEquivalence; + Ticker ticker; + + @GwtIncompatible(value="To be supported") + MapMaker keyEquivalence(Equivalence equivalence) { + Preconditions.checkState(this.keyEquivalence == null, "key equivalence was already set to %s", this.keyEquivalence); + this.keyEquivalence = Preconditions.checkNotNull(equivalence); + this.useCustomMap = true; + return this; + } + + Equivalence getKeyEquivalence() { + return MoreObjects.firstNonNull(this.keyEquivalence, this.getKeyStrength().defaultEquivalence()); + } + + public MapMaker initialCapacity(int initialCapacity) { + Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", this.initialCapacity); + Preconditions.checkArgument(initialCapacity >= 0); + this.initialCapacity = initialCapacity; + return this; + } + + int getInitialCapacity() { + return this.initialCapacity == -1 ? 16 : this.initialCapacity; + } + + @Deprecated + MapMaker maximumSize(int size) { + Preconditions.checkState(this.maximumSize == -1, "maximum size was already set to %s", this.maximumSize); + Preconditions.checkArgument(size >= 0, "maximum size must not be negative"); + this.maximumSize = size; + this.useCustomMap = true; + if (this.maximumSize == 0) { + this.nullRemovalCause = RemovalCause.SIZE; + } + return this; + } + + public MapMaker concurrencyLevel(int concurrencyLevel) { + Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", this.concurrencyLevel); + Preconditions.checkArgument(concurrencyLevel > 0); + this.concurrencyLevel = concurrencyLevel; + return this; + } + + int getConcurrencyLevel() { + return this.concurrencyLevel == -1 ? 4 : this.concurrencyLevel; + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public MapMaker weakKeys() { + return this.setKeyStrength(MapMakerInternalMap.Strength.WEAK); + } + + MapMaker setKeyStrength(MapMakerInternalMap.Strength strength) { + Preconditions.checkState(this.keyStrength == null, "Key strength was already set to %s", new Object[]{this.keyStrength}); + this.keyStrength = Preconditions.checkNotNull(strength); + Preconditions.checkArgument(this.keyStrength != MapMakerInternalMap.Strength.SOFT, "Soft keys are not supported"); + if (strength != MapMakerInternalMap.Strength.STRONG) { + this.useCustomMap = true; + } + return this; + } + + MapMakerInternalMap.Strength getKeyStrength() { + return MoreObjects.firstNonNull(this.keyStrength, MapMakerInternalMap.Strength.STRONG); + } + + @GwtIncompatible(value="java.lang.ref.WeakReference") + public MapMaker weakValues() { + return this.setValueStrength(MapMakerInternalMap.Strength.WEAK); + } + + @Deprecated + @GwtIncompatible(value="java.lang.ref.SoftReference") + public MapMaker softValues() { + return this.setValueStrength(MapMakerInternalMap.Strength.SOFT); + } + + MapMaker setValueStrength(MapMakerInternalMap.Strength strength) { + Preconditions.checkState(this.valueStrength == null, "Value strength was already set to %s", new Object[]{this.valueStrength}); + this.valueStrength = Preconditions.checkNotNull(strength); + if (strength != MapMakerInternalMap.Strength.STRONG) { + this.useCustomMap = true; + } + return this; + } + + MapMakerInternalMap.Strength getValueStrength() { + return MoreObjects.firstNonNull(this.valueStrength, MapMakerInternalMap.Strength.STRONG); + } + + @Deprecated + MapMaker expireAfterWrite(long duration, TimeUnit unit) { + this.checkExpiration(duration, unit); + this.expireAfterWriteNanos = unit.toNanos(duration); + if (duration == 0L && this.nullRemovalCause == null) { + this.nullRemovalCause = RemovalCause.EXPIRED; + } + this.useCustomMap = true; + return this; + } + + private void checkExpiration(long duration, TimeUnit unit) { + Preconditions.checkState(this.expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", this.expireAfterWriteNanos); + Preconditions.checkState(this.expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", this.expireAfterAccessNanos); + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[]{duration, unit}); + } + + long getExpireAfterWriteNanos() { + return this.expireAfterWriteNanos == -1L ? 0L : this.expireAfterWriteNanos; + } + + @Deprecated + @GwtIncompatible(value="To be supported") + MapMaker expireAfterAccess(long duration, TimeUnit unit) { + this.checkExpiration(duration, unit); + this.expireAfterAccessNanos = unit.toNanos(duration); + if (duration == 0L && this.nullRemovalCause == null) { + this.nullRemovalCause = RemovalCause.EXPIRED; + } + this.useCustomMap = true; + return this; + } + + long getExpireAfterAccessNanos() { + return this.expireAfterAccessNanos == -1L ? 0L : this.expireAfterAccessNanos; + } + + Ticker getTicker() { + return MoreObjects.firstNonNull(this.ticker, Ticker.systemTicker()); + } + + @Deprecated + @GwtIncompatible(value="To be supported") + GenericMapMaker removalListener(RemovalListener listener) { + Preconditions.checkState(this.removalListener == null); + MapMaker me = this; + me.removalListener = Preconditions.checkNotNull(listener); + this.useCustomMap = true; + return me; + } + + @Override + public ConcurrentMap makeMap() { + if (!this.useCustomMap) { + return new ConcurrentHashMap(this.getInitialCapacity(), 0.75f, this.getConcurrencyLevel()); + } + return (ConcurrentMap)((Object)(this.nullRemovalCause == null ? new MapMakerInternalMap(this) : new NullConcurrentMap(this))); + } + + @Override + @GwtIncompatible(value="MapMakerInternalMap") + MapMakerInternalMap makeCustomMap() { + return new MapMakerInternalMap(this); + } + + @Override + @Deprecated + ConcurrentMap makeComputingMap(Function computingFunction) { + return (ConcurrentMap)((Object)(this.nullRemovalCause == null ? new ComputingMapAdapter(this, computingFunction) : new NullComputingConcurrentMap(this, computingFunction))); + } + + public String toString() { + long l; + MoreObjects.ToStringHelper s = MoreObjects.toStringHelper(this); + if (this.initialCapacity != -1) { + s.add("initialCapacity", this.initialCapacity); + } + if (this.concurrencyLevel != -1) { + s.add("concurrencyLevel", this.concurrencyLevel); + } + if (this.maximumSize != -1) { + s.add("maximumSize", this.maximumSize); + } + if (this.expireAfterWriteNanos != -1L) { + l = this.expireAfterWriteNanos; + s.add("expireAfterWrite", new StringBuilder(22).append(l).append("ns").toString()); + } + if (this.expireAfterAccessNanos != -1L) { + l = this.expireAfterAccessNanos; + s.add("expireAfterAccess", new StringBuilder(22).append(l).append("ns").toString()); + } + if (this.keyStrength != null) { + s.add("keyStrength", Ascii.toLowerCase(this.keyStrength.toString())); + } + if (this.valueStrength != null) { + s.add("valueStrength", Ascii.toLowerCase(this.valueStrength.toString())); + } + if (this.keyEquivalence != null) { + s.addValue("keyEquivalence"); + } + if (this.removalListener != null) { + s.addValue("removalListener"); + } + return s.toString(); + } + + static final class ComputingMapAdapter + extends ComputingConcurrentHashMap + implements Serializable { + private static final long serialVersionUID = 0L; + + ComputingMapAdapter(MapMaker mapMaker, Function computingFunction) { + super(mapMaker, computingFunction); + } + + @Override + public V get(Object key) { + Object value; + try { + value = this.getOrCompute(key); + } + catch (ExecutionException e) { + Throwable cause = e.getCause(); + Throwables.propagateIfInstanceOf(cause, ComputationException.class); + throw new ComputationException(cause); + } + if (value == null) { + String string = String.valueOf(String.valueOf(this.computingFunction)); + String string2 = String.valueOf(String.valueOf(key)); + throw new NullPointerException(new StringBuilder(24 + string.length() + string2.length()).append(string).append(" returned null for key ").append(string2).append(".").toString()); + } + return value; + } + } + + static final class NullComputingConcurrentMap + extends NullConcurrentMap { + private static final long serialVersionUID = 0L; + final Function computingFunction; + + NullComputingConcurrentMap(MapMaker mapMaker, Function computingFunction) { + super(mapMaker); + this.computingFunction = Preconditions.checkNotNull(computingFunction); + } + + @Override + public V get(Object k) { + Object key = k; + V value = this.compute(key); + Preconditions.checkNotNull(value, "%s returned null for key %s.", this.computingFunction, key); + this.notifyRemoval(key, value); + return value; + } + + private V compute(K key) { + Preconditions.checkNotNull(key); + try { + return this.computingFunction.apply(key); + } + catch (ComputationException e) { + throw e; + } + catch (Throwable t) { + throw new ComputationException(t); + } + } + } + + static class NullConcurrentMap + extends AbstractMap + implements ConcurrentMap, + Serializable { + private static final long serialVersionUID = 0L; + private final RemovalListener removalListener; + private final RemovalCause removalCause; + + NullConcurrentMap(MapMaker mapMaker) { + this.removalListener = mapMaker.getRemovalListener(); + this.removalCause = mapMaker.nullRemovalCause; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return false; + } + + @Override + public boolean containsValue(@Nullable Object value) { + return false; + } + + @Override + public V get(@Nullable Object key) { + return null; + } + + void notifyRemoval(K key, V value) { + RemovalNotification notification = new RemovalNotification(key, value, this.removalCause); + this.removalListener.onRemoval(notification); + } + + @Override + public V put(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + this.notifyRemoval(key, value); + return null; + } + + @Override + public V putIfAbsent(K key, V value) { + return this.put(key, value); + } + + @Override + public V remove(@Nullable Object key) { + return null; + } + + @Override + public boolean remove(@Nullable Object key, @Nullable Object value) { + return false; + } + + @Override + public V replace(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + return null; + } + + @Override + public boolean replace(K key, @Nullable V oldValue, V newValue) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + return false; + } + + @Override + public Set> entrySet() { + return Collections.emptySet(); + } + } + + static enum RemovalCause { + EXPLICIT{ + + @Override + boolean wasEvicted() { + return false; + } + } + , + REPLACED{ + + @Override + boolean wasEvicted() { + return false; + } + } + , + COLLECTED{ + + @Override + boolean wasEvicted() { + return true; + } + } + , + EXPIRED{ + + @Override + boolean wasEvicted() { + return true; + } + } + , + SIZE{ + + @Override + boolean wasEvicted() { + return true; + } + }; + + + abstract boolean wasEvicted(); + } + + static final class RemovalNotification + extends ImmutableEntry { + private static final long serialVersionUID = 0L; + private final RemovalCause cause; + + RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) { + super(key, value); + this.cause = cause; + } + + public RemovalCause getCause() { + return this.cause; + } + + public boolean wasEvicted() { + return this.cause.wasEvicted(); + } + } + + static interface RemovalListener { + public void onRemoval(RemovalNotification var1); + } +} diff --git a/src/com/google/common/collect/MapMakerInternalMap.java b/src/com/google/common/collect/MapMakerInternalMap.java new file mode 100644 index 0000000..c920c8f --- /dev/null +++ b/src/com/google/common/collect/MapMakerInternalMap.java @@ -0,0 +1,3192 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Equivalence; +import com.google.common.base.Preconditions; +import com.google.common.base.Ticker; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.AbstractSequentialIterator; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ForwardingConcurrentMap; +import com.google.common.collect.GenericMapMaker; +import com.google.common.collect.Iterators; +import com.google.common.collect.MapMaker; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractQueue; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + +class MapMakerInternalMap +extends AbstractMap +implements ConcurrentMap, +Serializable { + static final int MAXIMUM_CAPACITY = 0x40000000; + static final int MAX_SEGMENTS = 65536; + static final int CONTAINS_VALUE_RETRIES = 3; + static final int DRAIN_THRESHOLD = 63; + static final int DRAIN_MAX = 16; + static final long CLEANUP_EXECUTOR_DELAY_SECS = 60L; + private static final Logger logger = Logger.getLogger(MapMakerInternalMap.class.getName()); + final transient int segmentMask; + final transient int segmentShift; + final transient Segment[] segments; + final int concurrencyLevel; + final Equivalence keyEquivalence; + final Equivalence valueEquivalence; + final Strength keyStrength; + final Strength valueStrength; + final int maximumSize; + final long expireAfterAccessNanos; + final long expireAfterWriteNanos; + final Queue> removalNotificationQueue; + final MapMaker.RemovalListener removalListener; + final transient EntryFactory entryFactory; + final Ticker ticker; + static final ValueReference UNSET = new ValueReference(){ + + @Override + public Object get() { + return null; + } + + @Override + public ReferenceEntry getEntry() { + return null; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, @Nullable Object value, ReferenceEntry entry) { + return this; + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public Object waitForValue() { + return null; + } + + @Override + public void clear(ValueReference newValue) { + } + }; + static final Queue DISCARDING_QUEUE = new AbstractQueue(){ + + @Override + public boolean offer(Object o) { + return true; + } + + @Override + public Object peek() { + return null; + } + + @Override + public Object poll() { + return null; + } + + @Override + public int size() { + return 0; + } + + @Override + public Iterator iterator() { + return Iterators.emptyIterator(); + } + }; + transient Set keySet; + transient Collection values; + transient Set> entrySet; + private static final long serialVersionUID = 5L; + + MapMakerInternalMap(MapMaker builder) { + int segmentSize; + int segmentCount; + this.concurrencyLevel = Math.min(builder.getConcurrencyLevel(), 65536); + this.keyStrength = builder.getKeyStrength(); + this.valueStrength = builder.getValueStrength(); + this.keyEquivalence = builder.getKeyEquivalence(); + this.valueEquivalence = this.valueStrength.defaultEquivalence(); + this.maximumSize = builder.maximumSize; + this.expireAfterAccessNanos = builder.getExpireAfterAccessNanos(); + this.expireAfterWriteNanos = builder.getExpireAfterWriteNanos(); + this.entryFactory = EntryFactory.getFactory(this.keyStrength, this.expires(), this.evictsBySize()); + this.ticker = builder.getTicker(); + this.removalListener = builder.getRemovalListener(); + this.removalNotificationQueue = this.removalListener == GenericMapMaker.NullListener.INSTANCE ? MapMakerInternalMap.discardingQueue() : new ConcurrentLinkedQueue(); + int initialCapacity = Math.min(builder.getInitialCapacity(), 0x40000000); + if (this.evictsBySize()) { + initialCapacity = Math.min(initialCapacity, this.maximumSize); + } + int segmentShift = 0; + for (segmentCount = 1; !(segmentCount >= this.concurrencyLevel || this.evictsBySize() && segmentCount * 2 > this.maximumSize); segmentCount <<= 1) { + ++segmentShift; + } + this.segmentShift = 32 - segmentShift; + this.segmentMask = segmentCount - 1; + this.segments = this.newSegmentArray(segmentCount); + int segmentCapacity = initialCapacity / segmentCount; + if (segmentCapacity * segmentCount < initialCapacity) { + ++segmentCapacity; + } + for (segmentSize = 1; segmentSize < segmentCapacity; segmentSize <<= 1) { + } + if (this.evictsBySize()) { + int maximumSegmentSize = this.maximumSize / segmentCount + 1; + int remainder = this.maximumSize % segmentCount; + for (int i = 0; i < this.segments.length; ++i) { + if (i == remainder) { + --maximumSegmentSize; + } + this.segments[i] = this.createSegment(segmentSize, maximumSegmentSize); + } + } else { + for (int i = 0; i < this.segments.length; ++i) { + this.segments[i] = this.createSegment(segmentSize, -1); + } + } + } + + boolean evictsBySize() { + return this.maximumSize != -1; + } + + boolean expires() { + return this.expiresAfterWrite() || this.expiresAfterAccess(); + } + + boolean expiresAfterWrite() { + return this.expireAfterWriteNanos > 0L; + } + + boolean expiresAfterAccess() { + return this.expireAfterAccessNanos > 0L; + } + + boolean usesKeyReferences() { + return this.keyStrength != Strength.STRONG; + } + + boolean usesValueReferences() { + return this.valueStrength != Strength.STRONG; + } + + static ValueReference unset() { + return UNSET; + } + + static ReferenceEntry nullEntry() { + return NullEntry.INSTANCE; + } + + static Queue discardingQueue() { + return DISCARDING_QUEUE; + } + + static int rehash(int h) { + h += h << 15 ^ 0xFFFFCD7D; + h ^= h >>> 10; + h += h << 3; + h ^= h >>> 6; + h += (h << 2) + (h << 14); + return h ^ h >>> 16; + } + + @VisibleForTesting + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) { + return this.segmentFor(hash).newEntry(key, hash, next); + } + + @VisibleForTesting + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) { + int hash = original.getHash(); + return this.segmentFor(hash).copyEntry(original, newNext); + } + + @VisibleForTesting + ValueReference newValueReference(ReferenceEntry entry, V value) { + int hash = entry.getHash(); + return this.valueStrength.referenceValue(this.segmentFor(hash), entry, value); + } + + int hash(Object key) { + int h = this.keyEquivalence.hash(key); + return MapMakerInternalMap.rehash(h); + } + + void reclaimValue(ValueReference valueReference) { + ReferenceEntry entry = valueReference.getEntry(); + int hash = entry.getHash(); + this.segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); + } + + void reclaimKey(ReferenceEntry entry) { + int hash = entry.getHash(); + this.segmentFor(hash).reclaimKey(entry, hash); + } + + @VisibleForTesting + boolean isLive(ReferenceEntry entry) { + return this.segmentFor(entry.getHash()).getLiveValue(entry) != null; + } + + Segment segmentFor(int hash) { + return this.segments[hash >>> this.segmentShift & this.segmentMask]; + } + + Segment createSegment(int initialCapacity, int maxSegmentSize) { + return new Segment(this, initialCapacity, maxSegmentSize); + } + + V getLiveValue(ReferenceEntry entry) { + if (entry.getKey() == null) { + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + return null; + } + if (this.expires() && this.isExpired(entry)) { + return null; + } + return value; + } + + boolean isExpired(ReferenceEntry entry) { + return this.isExpired(entry, this.ticker.read()); + } + + boolean isExpired(ReferenceEntry entry, long now) { + return now - entry.getExpirationTime() > 0L; + } + + static void connectExpirables(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextExpirable(next); + next.setPreviousExpirable(previous); + } + + static void nullifyExpirable(ReferenceEntry nulled) { + ReferenceEntry nullEntry = MapMakerInternalMap.nullEntry(); + nulled.setNextExpirable(nullEntry); + nulled.setPreviousExpirable(nullEntry); + } + + void processPendingNotifications() { + MapMaker.RemovalNotification notification; + while ((notification = this.removalNotificationQueue.poll()) != null) { + try { + this.removalListener.onRemoval(notification); + } + catch (Exception e) { + logger.log(Level.WARNING, "Exception thrown by removal listener", e); + } + } + } + + static void connectEvictables(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextEvictable(next); + next.setPreviousEvictable(previous); + } + + static void nullifyEvictable(ReferenceEntry nulled) { + ReferenceEntry nullEntry = MapMakerInternalMap.nullEntry(); + nulled.setNextEvictable(nullEntry); + nulled.setPreviousEvictable(nullEntry); + } + + final Segment[] newSegmentArray(int ssize) { + return new Segment[ssize]; + } + + @Override + public boolean isEmpty() { + int i; + long sum = 0L; + Segment[] segments = this.segments; + for (i = 0; i < segments.length; ++i) { + if (segments[i].count != 0) { + return false; + } + sum += (long)segments[i].modCount; + } + if (sum != 0L) { + for (i = 0; i < segments.length; ++i) { + if (segments[i].count != 0) { + return false; + } + sum -= (long)segments[i].modCount; + } + if (sum != 0L) { + return false; + } + } + return true; + } + + @Override + public int size() { + Segment[] segments = this.segments; + long sum = 0L; + for (int i = 0; i < segments.length; ++i) { + sum += (long)segments[i].count; + } + return Ints.saturatedCast(sum); + } + + @Override + public V get(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).get(key, hash); + } + + ReferenceEntry getEntry(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).getEntry(key, hash); + } + + @Override + public boolean containsKey(@Nullable Object key) { + if (key == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).containsKey(key, hash); + } + + @Override + public boolean containsValue(@Nullable Object value) { + if (value == null) { + return false; + } + Segment[] segments = this.segments; + long last = -1L; + for (int i = 0; i < 3; ++i) { + long sum = 0L; + for (Segment segment : segments) { + int c = segment.count; + AtomicReferenceArray table = segment.table; + for (int j = 0; j < table.length(); ++j) { + for (ReferenceEntry e = table.get(j); e != null; e = e.getNext()) { + V v = segment.getLiveValue(e); + if (v == null || !this.valueEquivalence.equivalent(value, v)) continue; + return true; + } + } + sum += (long)segment.modCount; + } + if (sum == last) break; + last = sum; + } + return false; + } + + @Override + public V put(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).put(key, hash, value, false); + } + + @Override + public V putIfAbsent(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).put(key, hash, value, true); + } + + @Override + public void putAll(Map m) { + for (Map.Entry e : m.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + @Override + public V remove(@Nullable Object key) { + if (key == null) { + return null; + } + int hash = this.hash(key); + return this.segmentFor(hash).remove(key, hash); + } + + @Override + public boolean remove(@Nullable Object key, @Nullable Object value) { + if (key == null || value == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).remove(key, hash, value); + } + + @Override + public boolean replace(K key, @Nullable V oldValue, V newValue) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + if (oldValue == null) { + return false; + } + int hash = this.hash(key); + return this.segmentFor(hash).replace(key, hash, oldValue, newValue); + } + + @Override + public V replace(K key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = this.hash(key); + return this.segmentFor(hash).replace(key, hash, value); + } + + @Override + public void clear() { + for (Segment segment : this.segments) { + segment.clear(); + } + } + + @Override + public Set keySet() { + KeySet ks = this.keySet; + return ks != null ? ks : (this.keySet = new KeySet()); + } + + @Override + public Collection values() { + Values vs = this.values; + return vs != null ? vs : (this.values = new Values()); + } + + @Override + public Set> entrySet() { + EntrySet es = this.entrySet; + return es != null ? es : (this.entrySet = new EntrySet()); + } + + Object writeReplace() { + return new SerializationProxy(this.keyStrength, this.valueStrength, this.keyEquivalence, this.valueEquivalence, this.expireAfterWriteNanos, this.expireAfterAccessNanos, this.maximumSize, this.concurrencyLevel, this.removalListener, this); + } + + private static final class SerializationProxy + extends AbstractSerializationProxy { + private static final long serialVersionUID = 3L; + + SerializationProxy(Strength keyStrength, Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate) { + super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate); + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + this.writeMapTo(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + MapMaker mapMaker = this.readMapMaker(in); + this.delegate = mapMaker.makeMap(); + this.readEntries(in); + } + + private Object readResolve() { + return this.delegate; + } + } + + static abstract class AbstractSerializationProxy + extends ForwardingConcurrentMap + implements Serializable { + private static final long serialVersionUID = 3L; + final Strength keyStrength; + final Strength valueStrength; + final Equivalence keyEquivalence; + final Equivalence valueEquivalence; + final long expireAfterWriteNanos; + final long expireAfterAccessNanos; + final int maximumSize; + final int concurrencyLevel; + final MapMaker.RemovalListener removalListener; + transient ConcurrentMap delegate; + + AbstractSerializationProxy(Strength keyStrength, Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate) { + this.keyStrength = keyStrength; + this.valueStrength = valueStrength; + this.keyEquivalence = keyEquivalence; + this.valueEquivalence = valueEquivalence; + this.expireAfterWriteNanos = expireAfterWriteNanos; + this.expireAfterAccessNanos = expireAfterAccessNanos; + this.maximumSize = maximumSize; + this.concurrencyLevel = concurrencyLevel; + this.removalListener = removalListener; + this.delegate = delegate; + } + + @Override + protected ConcurrentMap delegate() { + return this.delegate; + } + + void writeMapTo(ObjectOutputStream out) throws IOException { + out.writeInt(this.delegate.size()); + for (Map.Entry entry : this.delegate.entrySet()) { + out.writeObject(entry.getKey()); + out.writeObject(entry.getValue()); + } + out.writeObject(null); + } + + MapMaker readMapMaker(ObjectInputStream in) throws IOException { + int size = in.readInt(); + MapMaker mapMaker = ((MapMaker)new MapMaker().initialCapacity(size).setKeyStrength(this.keyStrength).setValueStrength(this.valueStrength).keyEquivalence((Equivalence)this.keyEquivalence)).concurrencyLevel(this.concurrencyLevel); + mapMaker.removalListener(this.removalListener); + if (this.expireAfterWriteNanos > 0L) { + mapMaker.expireAfterWrite(this.expireAfterWriteNanos, TimeUnit.NANOSECONDS); + } + if (this.expireAfterAccessNanos > 0L) { + mapMaker.expireAfterAccess(this.expireAfterAccessNanos, TimeUnit.NANOSECONDS); + } + if (this.maximumSize != -1) { + mapMaker.maximumSize(this.maximumSize); + } + return mapMaker; + } + + void readEntries(ObjectInputStream in) throws IOException, ClassNotFoundException { + Object key; + while ((key = in.readObject()) != null) { + Object value = in.readObject(); + this.delegate.put(key, value); + } + } + } + + final class EntrySet + extends AbstractSet> { + EntrySet() { + } + + @Override + public Iterator> iterator() { + return new EntryIterator(); + } + + @Override + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + if (key == null) { + return false; + } + Object v = MapMakerInternalMap.this.get(key); + return v != null && MapMakerInternalMap.this.valueEquivalence.equivalent(e.getValue(), v); + } + + @Override + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + return key != null && MapMakerInternalMap.this.remove(key, e.getValue()); + } + + @Override + public int size() { + return MapMakerInternalMap.this.size(); + } + + @Override + public boolean isEmpty() { + return MapMakerInternalMap.this.isEmpty(); + } + + @Override + public void clear() { + MapMakerInternalMap.this.clear(); + } + } + + final class Values + extends AbstractCollection { + Values() { + } + + @Override + public Iterator iterator() { + return new ValueIterator(); + } + + @Override + public int size() { + return MapMakerInternalMap.this.size(); + } + + @Override + public boolean isEmpty() { + return MapMakerInternalMap.this.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return MapMakerInternalMap.this.containsValue(o); + } + + @Override + public void clear() { + MapMakerInternalMap.this.clear(); + } + } + + final class KeySet + extends AbstractSet { + KeySet() { + } + + @Override + public Iterator iterator() { + return new KeyIterator(); + } + + @Override + public int size() { + return MapMakerInternalMap.this.size(); + } + + @Override + public boolean isEmpty() { + return MapMakerInternalMap.this.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return MapMakerInternalMap.this.containsKey(o); + } + + @Override + public boolean remove(Object o) { + return MapMakerInternalMap.this.remove(o) != null; + } + + @Override + public void clear() { + MapMakerInternalMap.this.clear(); + } + } + + final class EntryIterator + extends HashIterator> { + EntryIterator() { + } + + @Override + public Map.Entry next() { + return this.nextEntry(); + } + } + + final class WriteThroughEntry + extends AbstractMapEntry { + final K key; + V value; + + WriteThroughEntry(K key, V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public V getValue() { + return this.value; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Map.Entry) { + Map.Entry that = (Map.Entry)object; + return this.key.equals(that.getKey()) && this.value.equals(that.getValue()); + } + return false; + } + + @Override + public int hashCode() { + return this.key.hashCode() ^ this.value.hashCode(); + } + + @Override + public V setValue(V newValue) { + Object oldValue = MapMakerInternalMap.this.put(this.key, newValue); + this.value = newValue; + return oldValue; + } + } + + final class ValueIterator + extends HashIterator { + ValueIterator() { + } + + @Override + public V next() { + return this.nextEntry().getValue(); + } + } + + final class KeyIterator + extends HashIterator { + KeyIterator() { + } + + @Override + public K next() { + return this.nextEntry().getKey(); + } + } + + abstract class HashIterator + implements Iterator { + int nextSegmentIndex; + int nextTableIndex; + Segment currentSegment; + AtomicReferenceArray> currentTable; + ReferenceEntry nextEntry; + WriteThroughEntry nextExternal; + WriteThroughEntry lastReturned; + + HashIterator() { + this.nextSegmentIndex = MapMakerInternalMap.this.segments.length - 1; + this.nextTableIndex = -1; + this.advance(); + } + + @Override + public abstract E next(); + + final void advance() { + this.nextExternal = null; + if (this.nextInChain()) { + return; + } + if (this.nextInTable()) { + return; + } + while (this.nextSegmentIndex >= 0) { + this.currentSegment = MapMakerInternalMap.this.segments[this.nextSegmentIndex--]; + if (this.currentSegment.count == 0) continue; + this.currentTable = this.currentSegment.table; + this.nextTableIndex = this.currentTable.length() - 1; + if (!this.nextInTable()) continue; + return; + } + } + + boolean nextInChain() { + if (this.nextEntry != null) { + this.nextEntry = this.nextEntry.getNext(); + while (this.nextEntry != null) { + if (this.advanceTo(this.nextEntry)) { + return true; + } + this.nextEntry = this.nextEntry.getNext(); + } + } + return false; + } + + boolean nextInTable() { + while (this.nextTableIndex >= 0) { + if ((this.nextEntry = this.currentTable.get(this.nextTableIndex--)) == null || !this.advanceTo(this.nextEntry) && !this.nextInChain()) continue; + return true; + } + return false; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean advanceTo(ReferenceEntry entry) { + try { + Object key = entry.getKey(); + Object value = MapMakerInternalMap.this.getLiveValue(entry); + if (value != null) { + this.nextExternal = new WriteThroughEntry(key, value); + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.currentSegment.postReadCleanup(); + } + } + + @Override + public boolean hasNext() { + return this.nextExternal != null; + } + + WriteThroughEntry nextEntry() { + if (this.nextExternal == null) { + throw new NoSuchElementException(); + } + this.lastReturned = this.nextExternal; + this.advance(); + return this.lastReturned; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.lastReturned != null); + MapMakerInternalMap.this.remove(this.lastReturned.getKey()); + this.lastReturned = null; + } + } + + static final class CleanupMapTask + implements Runnable { + final WeakReference> mapReference; + + public CleanupMapTask(MapMakerInternalMap map) { + this.mapReference = new WeakReference(map); + } + + @Override + public void run() { + MapMakerInternalMap map = (MapMakerInternalMap)this.mapReference.get(); + if (map == null) { + throw new CancellationException(); + } + for (Segment segment : map.segments) { + segment.runCleanup(); + } + } + } + + static final class ExpirationQueue + extends AbstractQueue> { + final ReferenceEntry head = new AbstractReferenceEntry(){ + ReferenceEntry nextExpirable = this; + ReferenceEntry previousExpirable = this; + + @Override + public long getExpirationTime() { + return Long.MAX_VALUE; + } + + @Override + public void setExpirationTime(long time) { + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + }; + + ExpirationQueue() { + } + + @Override + public boolean offer(ReferenceEntry entry) { + MapMakerInternalMap.connectExpirables(entry.getPreviousExpirable(), entry.getNextExpirable()); + MapMakerInternalMap.connectExpirables(this.head.getPreviousExpirable(), entry); + MapMakerInternalMap.connectExpirables(entry, this.head); + return true; + } + + @Override + public ReferenceEntry peek() { + ReferenceEntry next = this.head.getNextExpirable(); + return next == this.head ? null : next; + } + + @Override + public ReferenceEntry poll() { + ReferenceEntry next = this.head.getNextExpirable(); + if (next == this.head) { + return null; + } + this.remove(next); + return next; + } + + @Override + public boolean remove(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + ReferenceEntry previous = e.getPreviousExpirable(); + ReferenceEntry next = e.getNextExpirable(); + MapMakerInternalMap.connectExpirables(previous, next); + MapMakerInternalMap.nullifyExpirable(e); + return next != NullEntry.INSTANCE; + } + + @Override + public boolean contains(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + return e.getNextExpirable() != NullEntry.INSTANCE; + } + + @Override + public boolean isEmpty() { + return this.head.getNextExpirable() == this.head; + } + + @Override + public int size() { + int size = 0; + for (ReferenceEntry e = this.head.getNextExpirable(); e != this.head; e = e.getNextExpirable()) { + ++size; + } + return size; + } + + @Override + public void clear() { + ReferenceEntry e = this.head.getNextExpirable(); + while (e != this.head) { + ReferenceEntry next = e.getNextExpirable(); + MapMakerInternalMap.nullifyExpirable(e); + e = next; + } + this.head.setNextExpirable(this.head); + this.head.setPreviousExpirable(this.head); + } + + @Override + public Iterator> iterator() { + return new AbstractSequentialIterator>((ReferenceEntry)this.peek()){ + + @Override + protected ReferenceEntry computeNext(ReferenceEntry previous) { + ReferenceEntry next = previous.getNextExpirable(); + return next == ExpirationQueue.this.head ? null : next; + } + }; + } + } + + static final class EvictionQueue + extends AbstractQueue> { + final ReferenceEntry head = new AbstractReferenceEntry(){ + ReferenceEntry nextEvictable = this; + ReferenceEntry previousEvictable = this; + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + }; + + EvictionQueue() { + } + + @Override + public boolean offer(ReferenceEntry entry) { + MapMakerInternalMap.connectEvictables(entry.getPreviousEvictable(), entry.getNextEvictable()); + MapMakerInternalMap.connectEvictables(this.head.getPreviousEvictable(), entry); + MapMakerInternalMap.connectEvictables(entry, this.head); + return true; + } + + @Override + public ReferenceEntry peek() { + ReferenceEntry next = this.head.getNextEvictable(); + return next == this.head ? null : next; + } + + @Override + public ReferenceEntry poll() { + ReferenceEntry next = this.head.getNextEvictable(); + if (next == this.head) { + return null; + } + this.remove(next); + return next; + } + + @Override + public boolean remove(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + ReferenceEntry previous = e.getPreviousEvictable(); + ReferenceEntry next = e.getNextEvictable(); + MapMakerInternalMap.connectEvictables(previous, next); + MapMakerInternalMap.nullifyEvictable(e); + return next != NullEntry.INSTANCE; + } + + @Override + public boolean contains(Object o) { + ReferenceEntry e = (ReferenceEntry)o; + return e.getNextEvictable() != NullEntry.INSTANCE; + } + + @Override + public boolean isEmpty() { + return this.head.getNextEvictable() == this.head; + } + + @Override + public int size() { + int size = 0; + for (ReferenceEntry e = this.head.getNextEvictable(); e != this.head; e = e.getNextEvictable()) { + ++size; + } + return size; + } + + @Override + public void clear() { + ReferenceEntry e = this.head.getNextEvictable(); + while (e != this.head) { + ReferenceEntry next = e.getNextEvictable(); + MapMakerInternalMap.nullifyEvictable(e); + e = next; + } + this.head.setNextEvictable(this.head); + this.head.setPreviousEvictable(this.head); + } + + @Override + public Iterator> iterator() { + return new AbstractSequentialIterator>((ReferenceEntry)this.peek()){ + + @Override + protected ReferenceEntry computeNext(ReferenceEntry previous) { + ReferenceEntry next = previous.getNextEvictable(); + return next == EvictionQueue.this.head ? null : next; + } + }; + } + } + + static class Segment + extends ReentrantLock { + final MapMakerInternalMap map; + volatile int count; + int modCount; + int threshold; + volatile AtomicReferenceArray> table; + final int maxSegmentSize; + final ReferenceQueue keyReferenceQueue; + final ReferenceQueue valueReferenceQueue; + final Queue> recencyQueue; + final AtomicInteger readCount = new AtomicInteger(); + @GuardedBy(value="Segment.this") + final Queue> evictionQueue; + @GuardedBy(value="Segment.this") + final Queue> expirationQueue; + + Segment(MapMakerInternalMap map, int initialCapacity, int maxSegmentSize) { + this.map = map; + this.maxSegmentSize = maxSegmentSize; + this.initTable(this.newEntryArray(initialCapacity)); + this.keyReferenceQueue = map.usesKeyReferences() ? new ReferenceQueue() : null; + this.valueReferenceQueue = map.usesValueReferences() ? new ReferenceQueue() : null; + this.recencyQueue = map.evictsBySize() || map.expiresAfterAccess() ? new ConcurrentLinkedQueue() : MapMakerInternalMap.discardingQueue(); + this.evictionQueue = map.evictsBySize() ? new EvictionQueue() : MapMakerInternalMap.discardingQueue(); + this.expirationQueue = map.expires() ? new ExpirationQueue() : MapMakerInternalMap.discardingQueue(); + } + + AtomicReferenceArray> newEntryArray(int size) { + return new AtomicReferenceArray>(size); + } + + void initTable(AtomicReferenceArray> newTable) { + this.threshold = newTable.length() * 3 / 4; + if (this.threshold == this.maxSegmentSize) { + ++this.threshold; + } + this.table = newTable; + } + + @GuardedBy(value="Segment.this") + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) { + return this.map.entryFactory.newEntry(this, key, hash, next); + } + + @GuardedBy(value="Segment.this") + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) { + if (original.getKey() == null) { + return null; + } + ValueReference valueReference = original.getValueReference(); + V value = valueReference.get(); + if (value == null && !valueReference.isComputingReference()) { + return null; + } + ReferenceEntry newEntry = this.map.entryFactory.copyEntry(this, original, newNext); + newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, value, newEntry)); + return newEntry; + } + + @GuardedBy(value="Segment.this") + void setValue(ReferenceEntry entry, V value) { + ValueReference valueReference = this.map.valueStrength.referenceValue(this, entry, value); + entry.setValueReference(valueReference); + this.recordWrite(entry); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void tryDrainReferenceQueues() { + if (this.tryLock()) { + try { + this.drainReferenceQueues(); + } + finally { + this.unlock(); + } + } + } + + @GuardedBy(value="Segment.this") + void drainReferenceQueues() { + if (this.map.usesKeyReferences()) { + this.drainKeyReferenceQueue(); + } + if (this.map.usesValueReferences()) { + this.drainValueReferenceQueue(); + } + } + + @GuardedBy(value="Segment.this") + void drainKeyReferenceQueue() { + Reference ref; + int i = 0; + while ((ref = this.keyReferenceQueue.poll()) != null) { + ReferenceEntry entry = (ReferenceEntry)((Object)ref); + this.map.reclaimKey(entry); + if (++i != 16) continue; + break; + } + } + + @GuardedBy(value="Segment.this") + void drainValueReferenceQueue() { + Reference ref; + int i = 0; + while ((ref = this.valueReferenceQueue.poll()) != null) { + ValueReference valueReference = (ValueReference)((Object)ref); + this.map.reclaimValue(valueReference); + if (++i != 16) continue; + break; + } + } + + void clearReferenceQueues() { + if (this.map.usesKeyReferences()) { + this.clearKeyReferenceQueue(); + } + if (this.map.usesValueReferences()) { + this.clearValueReferenceQueue(); + } + } + + void clearKeyReferenceQueue() { + while (this.keyReferenceQueue.poll() != null) { + } + } + + void clearValueReferenceQueue() { + while (this.valueReferenceQueue.poll() != null) { + } + } + + void recordRead(ReferenceEntry entry) { + if (this.map.expiresAfterAccess()) { + this.recordExpirationTime(entry, this.map.expireAfterAccessNanos); + } + this.recencyQueue.add(entry); + } + + @GuardedBy(value="Segment.this") + void recordLockedRead(ReferenceEntry entry) { + this.evictionQueue.add(entry); + if (this.map.expiresAfterAccess()) { + this.recordExpirationTime(entry, this.map.expireAfterAccessNanos); + this.expirationQueue.add(entry); + } + } + + @GuardedBy(value="Segment.this") + void recordWrite(ReferenceEntry entry) { + this.drainRecencyQueue(); + this.evictionQueue.add(entry); + if (this.map.expires()) { + long expiration = this.map.expiresAfterAccess() ? this.map.expireAfterAccessNanos : this.map.expireAfterWriteNanos; + this.recordExpirationTime(entry, expiration); + this.expirationQueue.add(entry); + } + } + + @GuardedBy(value="Segment.this") + void drainRecencyQueue() { + ReferenceEntry e; + while ((e = this.recencyQueue.poll()) != null) { + if (this.evictionQueue.contains(e)) { + this.evictionQueue.add(e); + } + if (!this.map.expiresAfterAccess() || !this.expirationQueue.contains(e)) continue; + this.expirationQueue.add(e); + } + } + + void recordExpirationTime(ReferenceEntry entry, long expirationNanos) { + entry.setExpirationTime(this.map.ticker.read() + expirationNanos); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void tryExpireEntries() { + if (this.tryLock()) { + try { + this.expireEntries(); + } + finally { + this.unlock(); + } + } + } + + @GuardedBy(value="Segment.this") + void expireEntries() { + ReferenceEntry e; + this.drainRecencyQueue(); + if (this.expirationQueue.isEmpty()) { + return; + } + long now = this.map.ticker.read(); + while ((e = this.expirationQueue.peek()) != null && this.map.isExpired(e, now)) { + if (!this.removeEntry(e, e.getHash(), MapMaker.RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + } + + void enqueueNotification(ReferenceEntry entry, MapMaker.RemovalCause cause) { + this.enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference().get(), cause); + } + + void enqueueNotification(@Nullable K key, int hash, @Nullable V value, MapMaker.RemovalCause cause) { + if (this.map.removalNotificationQueue != DISCARDING_QUEUE) { + MapMaker.RemovalNotification notification = new MapMaker.RemovalNotification(key, value, cause); + this.map.removalNotificationQueue.offer(notification); + } + } + + @GuardedBy(value="Segment.this") + boolean evictEntries() { + if (this.map.evictsBySize() && this.count >= this.maxSegmentSize) { + this.drainRecencyQueue(); + ReferenceEntry e = this.evictionQueue.remove(); + if (!this.removeEntry(e, e.getHash(), MapMaker.RemovalCause.SIZE)) { + throw new AssertionError(); + } + return true; + } + return false; + } + + ReferenceEntry getFirst(int hash) { + AtomicReferenceArray> table = this.table; + return table.get(hash & table.length() - 1); + } + + ReferenceEntry getEntry(Object key, int hash) { + if (this.count != 0) { + for (ReferenceEntry e = this.getFirst(hash); e != null; e = e.getNext()) { + if (e.getHash() != hash) continue; + K entryKey = e.getKey(); + if (entryKey == null) { + this.tryDrainReferenceQueues(); + continue; + } + if (!this.map.keyEquivalence.equivalent(key, entryKey)) continue; + return e; + } + } + return null; + } + + ReferenceEntry getLiveEntry(Object key, int hash) { + ReferenceEntry e = this.getEntry(key, hash); + if (e == null) { + return null; + } + if (this.map.expires() && this.map.isExpired(e)) { + this.tryExpireEntries(); + return null; + } + return e; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V get(Object key, int hash) { + try { + ReferenceEntry e = this.getLiveEntry(key, hash); + if (e == null) { + V v = null; + return v; + } + V value = e.getValueReference().get(); + if (value != null) { + this.recordRead(e); + } else { + this.tryDrainReferenceQueues(); + } + V v = value; + return v; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean containsKey(Object key, int hash) { + try { + if (this.count != 0) { + ReferenceEntry e = this.getLiveEntry(key, hash); + if (e == null) { + boolean bl = false; + return bl; + } + boolean bl = e.getValueReference().get() != null; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @VisibleForTesting + boolean containsValue(Object value) { + try { + if (this.count != 0) { + AtomicReferenceArray> table = this.table; + int length = table.length(); + for (int i = 0; i < length; ++i) { + for (ReferenceEntry e = table.get(i); e != null; e = e.getNext()) { + V entryValue = this.getLiveValue(e); + if (entryValue == null || !this.map.valueEquivalence.equivalent(value, entryValue)) continue; + boolean bl = true; + return bl; + } + } + } + boolean bl = false; + return bl; + } + finally { + this.postReadCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V put(K key, int hash, V value, boolean onlyIfAbsent) { + this.lock(); + try { + ReferenceEntry first; + this.preWriteCleanup(); + int newCount = this.count + 1; + if (newCount > this.threshold) { + this.expand(); + newCount = this.count + 1; + } + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + ++this.modCount; + this.setValue(e, value); + if (!valueReference.isComputingReference()) { + this.enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + newCount = this.count; + } else if (this.evictEntries()) { + newCount = this.count + 1; + } + this.count = newCount; + V v = null; + return v; + } + if (onlyIfAbsent) { + this.recordLockedRead(e); + V v = entryValue; + return v; + } + ++this.modCount; + this.enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + this.setValue(e, value); + V v = entryValue; + return v; + } + ++this.modCount; + ReferenceEntry newEntry = this.newEntry(key, hash, first); + this.setValue(newEntry, value); + table.set(index, newEntry); + if (this.evictEntries()) { + newCount = this.count + 1; + } + this.count = newCount; + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + @GuardedBy(value="Segment.this") + void expand() { + AtomicReferenceArray> oldTable = this.table; + int oldCapacity = oldTable.length(); + if (oldCapacity >= 0x40000000) { + return; + } + int newCount = this.count; + AtomicReferenceArray> newTable = this.newEntryArray(oldCapacity << 1); + this.threshold = newTable.length() * 3 / 4; + int newMask = newTable.length() - 1; + for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) { + int newIndex; + ReferenceEntry e; + ReferenceEntry head = oldTable.get(oldIndex); + if (head == null) continue; + ReferenceEntry next = head.getNext(); + int headIndex = head.getHash() & newMask; + if (next == null) { + newTable.set(headIndex, head); + continue; + } + ReferenceEntry tail = head; + int tailIndex = headIndex; + for (e = next; e != null; e = e.getNext()) { + newIndex = e.getHash() & newMask; + if (newIndex == tailIndex) continue; + tailIndex = newIndex; + tail = e; + } + newTable.set(tailIndex, tail); + for (e = head; e != tail; e = e.getNext()) { + newIndex = e.getHash() & newMask; + ReferenceEntry newNext = newTable.get(newIndex); + ReferenceEntry newFirst = this.copyEntry(e, newNext); + if (newFirst != null) { + newTable.set(newIndex, newFirst); + continue; + } + this.removeCollectedEntry(e); + --newCount; + } + } + this.table = newTable; + this.count = newCount; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean replace(K key, int hash, V oldValue, V newValue) { + this.lock(); + try { + ReferenceEntry first; + this.preWriteCleanup(); + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + if (this.isCollected(valueReference)) { + int newCount = this.count - 1; + ++this.modCount; + this.enqueueNotification(entryKey, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + } + boolean bl = false; + return bl; + } + if (this.map.valueEquivalence.equivalent(oldValue, entryValue)) { + ++this.modCount; + this.enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + this.setValue(e, newValue); + boolean bl = true; + return bl; + } + this.recordLockedRead(e); + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V replace(K key, int hash, V newValue) { + this.lock(); + try { + ReferenceEntry first; + this.preWriteCleanup(); + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue == null) { + if (this.isCollected(valueReference)) { + int newCount = this.count - 1; + ++this.modCount; + this.enqueueNotification(entryKey, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + } + V v = null; + return v; + } + ++this.modCount; + this.enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + this.setValue(e, newValue); + V v = entryValue; + return v; + } + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + V remove(Object key, int hash) { + this.lock(); + try { + ReferenceEntry first; + this.preWriteCleanup(); + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + MapMaker.RemovalCause cause; + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (entryValue != null) { + cause = MapMaker.RemovalCause.EXPLICIT; + } else if (this.isCollected(valueReference)) { + cause = MapMaker.RemovalCause.COLLECTED; + } else { + V v = null; + return v; + } + ++this.modCount; + this.enqueueNotification(entryKey, hash, entryValue, cause); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + V v = entryValue; + return v; + } + V v = null; + return v; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean remove(Object key, int hash, Object value) { + this.lock(); + try { + ReferenceEntry first; + this.preWriteCleanup(); + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + MapMaker.RemovalCause cause; + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + if (this.map.valueEquivalence.equivalent(value, entryValue)) { + cause = MapMaker.RemovalCause.EXPLICIT; + } else if (this.isCollected(valueReference)) { + cause = MapMaker.RemovalCause.COLLECTED; + } else { + boolean bl = false; + return bl; + } + ++this.modCount; + this.enqueueNotification(entryKey, hash, entryValue, cause); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = cause == MapMaker.RemovalCause.EXPLICIT; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void clear() { + if (this.count != 0) { + this.lock(); + try { + int i; + AtomicReferenceArray> table = this.table; + if (this.map.removalNotificationQueue != DISCARDING_QUEUE) { + for (i = 0; i < table.length(); ++i) { + for (ReferenceEntry e = table.get(i); e != null; e = e.getNext()) { + if (e.getValueReference().isComputingReference()) continue; + this.enqueueNotification(e, MapMaker.RemovalCause.EXPLICIT); + } + } + } + for (i = 0; i < table.length(); ++i) { + table.set(i, null); + } + this.clearReferenceQueues(); + this.evictionQueue.clear(); + this.expirationQueue.clear(); + this.readCount.set(0); + ++this.modCount; + this.count = 0; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + } + + @GuardedBy(value="Segment.this") + ReferenceEntry removeFromChain(ReferenceEntry first, ReferenceEntry entry) { + this.evictionQueue.remove(entry); + this.expirationQueue.remove(entry); + int newCount = this.count; + ReferenceEntry newFirst = entry.getNext(); + for (ReferenceEntry e = first; e != entry; e = e.getNext()) { + ReferenceEntry next = this.copyEntry(e, newFirst); + if (next != null) { + newFirst = next; + continue; + } + this.removeCollectedEntry(e); + --newCount; + } + this.count = newCount; + return newFirst; + } + + void removeCollectedEntry(ReferenceEntry entry) { + this.enqueueNotification(entry, MapMaker.RemovalCause.COLLECTED); + this.evictionQueue.remove(entry); + this.expirationQueue.remove(entry); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean reclaimKey(ReferenceEntry entry, int hash) { + this.lock(); + try { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + if (e != entry) continue; + ++this.modCount; + this.enqueueNotification(e.getKey(), hash, e.getValueReference().get(), MapMaker.RemovalCause.COLLECTED); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean reclaimValue(K key, int hash, ValueReference valueReference) { + this.lock(); + try { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference v = e.getValueReference(); + if (v == valueReference) { + ++this.modCount; + this.enqueueNotification(key, hash, valueReference.get(), MapMaker.RemovalCause.COLLECTED); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + if (!this.isHeldByCurrentThread()) { + this.postWriteCleanup(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + boolean clearValue(K key, int hash, ValueReference valueReference) { + this.lock(); + try { + ReferenceEntry first; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if (e.getHash() != hash || entryKey == null || !this.map.keyEquivalence.equivalent(key, entryKey)) continue; + ValueReference v = e.getValueReference(); + if (v == valueReference) { + ReferenceEntry newFirst = this.removeFromChain(first, e); + table.set(index, newFirst); + boolean bl = true; + return bl; + } + boolean bl = false; + return bl; + } + boolean bl = false; + return bl; + } + finally { + this.unlock(); + this.postWriteCleanup(); + } + } + + @GuardedBy(value="Segment.this") + boolean removeEntry(ReferenceEntry entry, int hash, MapMaker.RemovalCause cause) { + ReferenceEntry first; + int newCount = this.count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + for (ReferenceEntry e = first = table.get(index); e != null; e = e.getNext()) { + if (e != entry) continue; + ++this.modCount; + this.enqueueNotification(e.getKey(), hash, e.getValueReference().get(), cause); + ReferenceEntry newFirst = this.removeFromChain(first, e); + newCount = this.count - 1; + table.set(index, newFirst); + this.count = newCount; + return true; + } + return false; + } + + boolean isCollected(ValueReference valueReference) { + if (valueReference.isComputingReference()) { + return false; + } + return valueReference.get() == null; + } + + V getLiveValue(ReferenceEntry entry) { + if (entry.getKey() == null) { + this.tryDrainReferenceQueues(); + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + this.tryDrainReferenceQueues(); + return null; + } + if (this.map.expires() && this.map.isExpired(entry)) { + this.tryExpireEntries(); + return null; + } + return value; + } + + void postReadCleanup() { + if ((this.readCount.incrementAndGet() & 0x3F) == 0) { + this.runCleanup(); + } + } + + @GuardedBy(value="Segment.this") + void preWriteCleanup() { + this.runLockedCleanup(); + } + + void postWriteCleanup() { + this.runUnlockedCleanup(); + } + + void runCleanup() { + this.runLockedCleanup(); + this.runUnlockedCleanup(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void runLockedCleanup() { + if (this.tryLock()) { + try { + this.drainReferenceQueues(); + this.expireEntries(); + this.readCount.set(0); + } + finally { + this.unlock(); + } + } + } + + void runUnlockedCleanup() { + if (!this.isHeldByCurrentThread()) { + this.map.processPendingNotifications(); + } + } + } + + static final class StrongValueReference + implements ValueReference { + final V referent; + + StrongValueReference(V referent) { + this.referent = referent; + } + + @Override + public V get() { + return this.referent; + } + + @Override + public ReferenceEntry getEntry() { + return null; + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return this; + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public V waitForValue() { + return this.get(); + } + + @Override + public void clear(ValueReference newValue) { + } + } + + static final class SoftValueReference + extends SoftReference + implements ValueReference { + final ReferenceEntry entry; + + SoftValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry) { + super(referent, queue); + this.entry = entry; + } + + @Override + public ReferenceEntry getEntry() { + return this.entry; + } + + @Override + public void clear(ValueReference newValue) { + this.clear(); + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new SoftValueReference(queue, value, entry); + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public V waitForValue() { + return (V)this.get(); + } + } + + static final class WeakValueReference + extends WeakReference + implements ValueReference { + final ReferenceEntry entry; + + WeakValueReference(ReferenceQueue queue, V referent, ReferenceEntry entry) { + super(referent, queue); + this.entry = entry; + } + + @Override + public ReferenceEntry getEntry() { + return this.entry; + } + + @Override + public void clear(ValueReference newValue) { + this.clear(); + } + + @Override + public ValueReference copyFor(ReferenceQueue queue, V value, ReferenceEntry entry) { + return new WeakValueReference(queue, value, entry); + } + + @Override + public boolean isComputingReference() { + return false; + } + + @Override + public V waitForValue() { + return (V)this.get(); + } + } + + static final class WeakExpirableEvictableEntry + extends WeakEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + WeakExpirableEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class WeakEvictableEntry + extends WeakEntry + implements ReferenceEntry { + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + WeakEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class WeakExpirableEntry + extends WeakEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + WeakExpirableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + } + + static class WeakEntry + extends WeakReference + implements ReferenceEntry { + final int hash; + final ReferenceEntry next; + volatile ValueReference valueReference = MapMakerInternalMap.unset(); + + WeakEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(key, queue); + this.hash = hash; + this.next = next; + } + + @Override + public K getKey() { + return (K)this.get(); + } + + @Override + public long getExpirationTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setExpirationTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ValueReference getValueReference() { + return this.valueReference; + } + + @Override + public void setValueReference(ValueReference valueReference) { + ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + @Override + public int getHash() { + return this.hash; + } + + @Override + public ReferenceEntry getNext() { + return this.next; + } + } + + static final class SoftExpirableEvictableEntry + extends SoftEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + SoftExpirableEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class SoftEvictableEntry + extends SoftEntry + implements ReferenceEntry { + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + SoftEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class SoftExpirableEntry + extends SoftEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + SoftExpirableEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(queue, key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + } + + static class SoftEntry + extends SoftReference + implements ReferenceEntry { + final int hash; + final ReferenceEntry next; + volatile ValueReference valueReference = MapMakerInternalMap.unset(); + + SoftEntry(ReferenceQueue queue, K key, int hash, @Nullable ReferenceEntry next) { + super(key, queue); + this.hash = hash; + this.next = next; + } + + @Override + public K getKey() { + return (K)this.get(); + } + + @Override + public long getExpirationTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setExpirationTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ValueReference getValueReference() { + return this.valueReference; + } + + @Override + public void setValueReference(ValueReference valueReference) { + ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + @Override + public int getHash() { + return this.hash; + } + + @Override + public ReferenceEntry getNext() { + return this.next; + } + } + + static final class StrongExpirableEvictableEntry + extends StrongEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + StrongExpirableEvictableEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class StrongEvictableEntry + extends StrongEntry + implements ReferenceEntry { + ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + StrongEvictableEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public ReferenceEntry getNextEvictable() { + return this.nextEvictable; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + this.nextEvictable = next; + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this.previousEvictable; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + this.previousEvictable = previous; + } + } + + static final class StrongExpirableEntry + extends StrongEntry + implements ReferenceEntry { + volatile long time = Long.MAX_VALUE; + ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + StrongExpirableEntry(K key, int hash, @Nullable ReferenceEntry next) { + super(key, hash, next); + } + + @Override + public long getExpirationTime() { + return this.time; + } + + @Override + public void setExpirationTime(long time) { + this.time = time; + } + + @Override + public ReferenceEntry getNextExpirable() { + return this.nextExpirable; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + this.nextExpirable = next; + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this.previousExpirable; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + this.previousExpirable = previous; + } + } + + static class StrongEntry + implements ReferenceEntry { + final K key; + final int hash; + final ReferenceEntry next; + volatile ValueReference valueReference = MapMakerInternalMap.unset(); + + StrongEntry(K key, int hash, @Nullable ReferenceEntry next) { + this.key = key; + this.hash = hash; + this.next = next; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public long getExpirationTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setExpirationTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ValueReference getValueReference() { + return this.valueReference; + } + + @Override + public void setValueReference(ValueReference valueReference) { + ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + @Override + public int getHash() { + return this.hash; + } + + @Override + public ReferenceEntry getNext() { + return this.next; + } + } + + static abstract class AbstractReferenceEntry + implements ReferenceEntry { + AbstractReferenceEntry() { + } + + @Override + public ValueReference getValueReference() { + throw new UnsupportedOperationException(); + } + + @Override + public void setValueReference(ValueReference valueReference) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNext() { + throw new UnsupportedOperationException(); + } + + @Override + public int getHash() { + throw new UnsupportedOperationException(); + } + + @Override + public K getKey() { + throw new UnsupportedOperationException(); + } + + @Override + public long getExpirationTime() { + throw new UnsupportedOperationException(); + } + + @Override + public void setExpirationTime(long time) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousExpirable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getNextEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + throw new UnsupportedOperationException(); + } + + @Override + public ReferenceEntry getPreviousEvictable() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + throw new UnsupportedOperationException(); + } + } + + private static enum NullEntry implements ReferenceEntry + { + INSTANCE; + + + @Override + public ValueReference getValueReference() { + return null; + } + + @Override + public void setValueReference(ValueReference valueReference) { + } + + @Override + public ReferenceEntry getNext() { + return null; + } + + @Override + public int getHash() { + return 0; + } + + @Override + public Object getKey() { + return null; + } + + @Override + public long getExpirationTime() { + return 0L; + } + + @Override + public void setExpirationTime(long time) { + } + + @Override + public ReferenceEntry getNextExpirable() { + return this; + } + + @Override + public void setNextExpirable(ReferenceEntry next) { + } + + @Override + public ReferenceEntry getPreviousExpirable() { + return this; + } + + @Override + public void setPreviousExpirable(ReferenceEntry previous) { + } + + @Override + public ReferenceEntry getNextEvictable() { + return this; + } + + @Override + public void setNextEvictable(ReferenceEntry next) { + } + + @Override + public ReferenceEntry getPreviousEvictable() { + return this; + } + + @Override + public void setPreviousEvictable(ReferenceEntry previous) { + } + } + + static interface ReferenceEntry { + public ValueReference getValueReference(); + + public void setValueReference(ValueReference var1); + + public ReferenceEntry getNext(); + + public int getHash(); + + public K getKey(); + + public long getExpirationTime(); + + public void setExpirationTime(long var1); + + public ReferenceEntry getNextExpirable(); + + public void setNextExpirable(ReferenceEntry var1); + + public ReferenceEntry getPreviousExpirable(); + + public void setPreviousExpirable(ReferenceEntry var1); + + public ReferenceEntry getNextEvictable(); + + public void setNextEvictable(ReferenceEntry var1); + + public ReferenceEntry getPreviousEvictable(); + + public void setPreviousEvictable(ReferenceEntry var1); + } + + static interface ValueReference { + public V get(); + + public V waitForValue() throws ExecutionException; + + public ReferenceEntry getEntry(); + + public ValueReference copyFor(ReferenceQueue var1, @Nullable V var2, ReferenceEntry var3); + + public void clear(@Nullable ValueReference var1); + + public boolean isComputingReference(); + } + + static enum EntryFactory { + STRONG{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongEntry(key, hash, next); + } + } + , + STRONG_EXPIRABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongExpirableEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyExpirableEntry(original, newEntry); + return newEntry; + } + } + , + STRONG_EVICTABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongEvictableEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyEvictableEntry(original, newEntry); + return newEntry; + } + } + , + STRONG_EXPIRABLE_EVICTABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new StrongExpirableEvictableEntry(key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyExpirableEntry(original, newEntry); + this.copyEvictableEntry(original, newEntry); + return newEntry; + } + } + , + WEAK{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakEntry(segment.keyReferenceQueue, key, hash, next); + } + } + , + WEAK_EXPIRABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakExpirableEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyExpirableEntry(original, newEntry); + return newEntry; + } + } + , + WEAK_EVICTABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakEvictableEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyEvictableEntry(original, newEntry); + return newEntry; + } + } + , + WEAK_EXPIRABLE_EVICTABLE{ + + @Override + ReferenceEntry newEntry(Segment segment, K key, int hash, @Nullable ReferenceEntry next) { + return new WeakExpirableEvictableEntry(segment.keyReferenceQueue, key, hash, next); + } + + @Override + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + ReferenceEntry newEntry = super.copyEntry(segment, original, newNext); + this.copyExpirableEntry(original, newEntry); + this.copyEvictableEntry(original, newEntry); + return newEntry; + } + }; + + static final int EXPIRABLE_MASK = 1; + static final int EVICTABLE_MASK = 2; + static final EntryFactory[][] factories; + + static EntryFactory getFactory(Strength keyStrength, boolean expireAfterWrite, boolean evictsBySize) { + int flags = (expireAfterWrite ? 1 : 0) | (evictsBySize ? 2 : 0); + return factories[keyStrength.ordinal()][flags]; + } + + abstract ReferenceEntry newEntry(Segment var1, K var2, int var3, @Nullable ReferenceEntry var4); + + ReferenceEntry copyEntry(Segment segment, ReferenceEntry original, ReferenceEntry newNext) { + return this.newEntry(segment, original.getKey(), original.getHash(), newNext); + } + + void copyExpirableEntry(ReferenceEntry original, ReferenceEntry newEntry) { + newEntry.setExpirationTime(original.getExpirationTime()); + MapMakerInternalMap.connectExpirables(original.getPreviousExpirable(), newEntry); + MapMakerInternalMap.connectExpirables(newEntry, original.getNextExpirable()); + MapMakerInternalMap.nullifyExpirable(original); + } + + void copyEvictableEntry(ReferenceEntry original, ReferenceEntry newEntry) { + MapMakerInternalMap.connectEvictables(original.getPreviousEvictable(), newEntry); + MapMakerInternalMap.connectEvictables(newEntry, original.getNextEvictable()); + MapMakerInternalMap.nullifyEvictable(original); + } + + static { + factories = new EntryFactory[][]{{STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE}, new EntryFactory[0], {WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE}}; + } + } + + static enum Strength { + STRONG{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value) { + return new StrongValueReference(value); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.equals(); + } + } + , + SOFT{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value) { + return new SoftValueReference(segment.valueReferenceQueue, value, entry); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.identity(); + } + } + , + WEAK{ + + @Override + ValueReference referenceValue(Segment segment, ReferenceEntry entry, V value) { + return new WeakValueReference(segment.valueReferenceQueue, value, entry); + } + + @Override + Equivalence defaultEquivalence() { + return Equivalence.identity(); + } + }; + + + abstract ValueReference referenceValue(Segment var1, ReferenceEntry var2, V var3); + + abstract Equivalence defaultEquivalence(); + } +} diff --git a/src/com/google/common/collect/Maps.java b/src/com/google/common/collect/Maps.java new file mode 100644 index 0000000..b05a84f --- /dev/null +++ b/src/com/google/common/collect/Maps.java @@ -0,0 +1,2691 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.AbstractNavigableMap; +import com.google.common.collect.BiMap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ForwardingNavigableSet; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ForwardingSortedMap; +import com.google.common.collect.ForwardingSortedSet; +import com.google.common.collect.ImmutableEntry; +import com.google.common.collect.ImmutableEnumMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.MapDifference; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Ordering; +import com.google.common.collect.Platform; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedMapDifference; +import com.google.common.collect.Synchronized; +import com.google.common.collect.TransformedIterator; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Properties; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentMap; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Maps { + static final Joiner.MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("="); + + private Maps() { + } + + static Function, K> keyFunction() { + return EntryFunction.KEY; + } + + static Function, V> valueFunction() { + return EntryFunction.VALUE; + } + + static Iterator keyIterator(Iterator> entryIterator) { + return Iterators.transform(entryIterator, Maps.keyFunction()); + } + + static Iterator valueIterator(Iterator> entryIterator) { + return Iterators.transform(entryIterator, Maps.valueFunction()); + } + + static UnmodifiableIterator valueIterator(final UnmodifiableIterator> entryIterator) { + return new UnmodifiableIterator(){ + + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public V next() { + return ((Map.Entry)entryIterator.next()).getValue(); + } + }; + } + + @GwtCompatible(serializable=true) + @Beta + public static , V> ImmutableMap immutableEnumMap(Map map) { + if (map instanceof ImmutableEnumMap) { + ImmutableEnumMap result = (ImmutableEnumMap)map; + return result; + } + if (map.isEmpty()) { + return ImmutableMap.of(); + } + for (Map.Entry entry : map.entrySet()) { + Preconditions.checkNotNull(entry.getKey()); + Preconditions.checkNotNull(entry.getValue()); + } + return ImmutableEnumMap.asImmutable(new EnumMap(map)); + } + + public static HashMap newHashMap() { + return new HashMap(); + } + + public static HashMap newHashMapWithExpectedSize(int expectedSize) { + return new HashMap(Maps.capacity(expectedSize)); + } + + static int capacity(int expectedSize) { + if (expectedSize < 3) { + CollectPreconditions.checkNonnegative(expectedSize, "expectedSize"); + return expectedSize + 1; + } + if (expectedSize < 0x40000000) { + return expectedSize + expectedSize / 3; + } + return Integer.MAX_VALUE; + } + + public static HashMap newHashMap(Map map) { + return new HashMap(map); + } + + public static LinkedHashMap newLinkedHashMap() { + return new LinkedHashMap(); + } + + public static LinkedHashMap newLinkedHashMap(Map map) { + return new LinkedHashMap(map); + } + + public static ConcurrentMap newConcurrentMap() { + return new MapMaker().makeMap(); + } + + public static TreeMap newTreeMap() { + return new TreeMap(); + } + + public static TreeMap newTreeMap(SortedMap map) { + return new TreeMap(map); + } + + public static TreeMap newTreeMap(@Nullable Comparator comparator) { + return new TreeMap(comparator); + } + + public static , V> EnumMap newEnumMap(Class type) { + return new EnumMap(Preconditions.checkNotNull(type)); + } + + public static , V> EnumMap newEnumMap(Map map) { + return new EnumMap(map); + } + + public static IdentityHashMap newIdentityHashMap() { + return new IdentityHashMap(); + } + + public static MapDifference difference(Map left, Map right) { + if (left instanceof SortedMap) { + SortedMap sortedLeft = (SortedMap)left; + SortedMapDifference result = Maps.difference(sortedLeft, right); + return result; + } + return Maps.difference(left, right, Equivalence.equals()); + } + + @Beta + public static MapDifference difference(Map left, Map right, Equivalence valueEquivalence) { + Preconditions.checkNotNull(valueEquivalence); + HashMap onlyOnLeft = Maps.newHashMap(); + HashMap onlyOnRight = new HashMap(right); + HashMap onBoth = Maps.newHashMap(); + HashMap differences = Maps.newHashMap(); + Maps.doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences); + return new MapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); + } + + private static void doDifference(Map left, Map right, Equivalence valueEquivalence, Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) { + for (Map.Entry entry : left.entrySet()) { + K leftKey = entry.getKey(); + V leftValue = entry.getValue(); + if (right.containsKey(leftKey)) { + V rightValue = onlyOnRight.remove(leftKey); + if (valueEquivalence.equivalent(leftValue, rightValue)) { + onBoth.put(leftKey, leftValue); + continue; + } + differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue)); + continue; + } + onlyOnLeft.put(leftKey, leftValue); + } + } + + private static Map unmodifiableMap(Map map) { + if (map instanceof SortedMap) { + return Collections.unmodifiableSortedMap((SortedMap)map); + } + return Collections.unmodifiableMap(map); + } + + public static SortedMapDifference difference(SortedMap left, Map right) { + Preconditions.checkNotNull(left); + Preconditions.checkNotNull(right); + Comparator comparator = Maps.orNaturalOrder(left.comparator()); + TreeMap onlyOnLeft = Maps.newTreeMap(comparator); + TreeMap onlyOnRight = Maps.newTreeMap(comparator); + onlyOnRight.putAll(right); + TreeMap onBoth = Maps.newTreeMap(comparator); + TreeMap differences = Maps.newTreeMap(comparator); + Maps.doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences); + return new SortedMapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); + } + + static Comparator orNaturalOrder(@Nullable Comparator comparator) { + if (comparator != null) { + return comparator; + } + return Ordering.natural(); + } + + @Beta + public static Map asMap(Set set, Function function) { + if (set instanceof SortedSet) { + return Maps.asMap((SortedSet)set, function); + } + return new AsMapView(set, function); + } + + @Beta + public static SortedMap asMap(SortedSet set, Function function) { + return Platform.mapsAsMapSortedSet(set, function); + } + + static SortedMap asMapSortedIgnoreNavigable(SortedSet set, Function function) { + return new SortedAsMapView(set, function); + } + + @Beta + @GwtIncompatible(value="NavigableMap") + public static NavigableMap asMap(NavigableSet set, Function function) { + return new NavigableAsMapView(set, function); + } + + static Iterator> asMapEntryIterator(Set set, final Function function) { + return new TransformedIterator>(set.iterator()){ + + @Override + Map.Entry transform(K key) { + return Maps.immutableEntry(key, function.apply(key)); + } + }; + } + + private static Set removeOnlySet(final Set set) { + return new ForwardingSet(){ + + @Override + protected Set delegate() { + return set; + } + + @Override + public boolean add(E element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection es) { + throw new UnsupportedOperationException(); + } + }; + } + + private static SortedSet removeOnlySortedSet(final SortedSet set) { + return new ForwardingSortedSet(){ + + @Override + protected SortedSet delegate() { + return set; + } + + @Override + public boolean add(E element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection es) { + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet headSet(E toElement) { + return Maps.removeOnlySortedSet(super.headSet(toElement)); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return Maps.removeOnlySortedSet(super.subSet(fromElement, toElement)); + } + + @Override + public SortedSet tailSet(E fromElement) { + return Maps.removeOnlySortedSet(super.tailSet(fromElement)); + } + }; + } + + @GwtIncompatible(value="NavigableSet") + private static NavigableSet removeOnlyNavigableSet(final NavigableSet set) { + return new ForwardingNavigableSet(){ + + @Override + protected NavigableSet delegate() { + return set; + } + + @Override + public boolean add(E element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection es) { + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet headSet(E toElement) { + return Maps.removeOnlySortedSet(super.headSet(toElement)); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return Maps.removeOnlySortedSet(super.subSet(fromElement, toElement)); + } + + @Override + public SortedSet tailSet(E fromElement) { + return Maps.removeOnlySortedSet(super.tailSet(fromElement)); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return Maps.removeOnlyNavigableSet(super.headSet(toElement, inclusive)); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return Maps.removeOnlyNavigableSet(super.tailSet(fromElement, inclusive)); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return Maps.removeOnlyNavigableSet(super.subSet(fromElement, fromInclusive, toElement, toInclusive)); + } + + @Override + public NavigableSet descendingSet() { + return Maps.removeOnlyNavigableSet(super.descendingSet()); + } + }; + } + + @Beta + public static ImmutableMap toMap(Iterable keys, Function valueFunction) { + return Maps.toMap(keys.iterator(), valueFunction); + } + + @Beta + public static ImmutableMap toMap(Iterator keys, Function valueFunction) { + Preconditions.checkNotNull(valueFunction); + LinkedHashMap builder = Maps.newLinkedHashMap(); + while (keys.hasNext()) { + K key = keys.next(); + builder.put(key, valueFunction.apply(key)); + } + return ImmutableMap.copyOf(builder); + } + + public static ImmutableMap uniqueIndex(Iterable values, Function keyFunction) { + return Maps.uniqueIndex(values.iterator(), keyFunction); + } + + public static ImmutableMap uniqueIndex(Iterator values, Function keyFunction) { + Preconditions.checkNotNull(keyFunction); + ImmutableMap.Builder builder = ImmutableMap.builder(); + while (values.hasNext()) { + V value = values.next(); + builder.put(keyFunction.apply(value), value); + } + return builder.build(); + } + + @GwtIncompatible(value="java.util.Properties") + public static ImmutableMap fromProperties(Properties properties) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + Enumeration e = properties.propertyNames(); + while (e.hasMoreElements()) { + String key = (String)e.nextElement(); + builder.put(key, properties.getProperty(key)); + } + return builder.build(); + } + + @GwtCompatible(serializable=true) + public static Map.Entry immutableEntry(@Nullable K key, @Nullable V value) { + return new ImmutableEntry(key, value); + } + + static Set> unmodifiableEntrySet(Set> entrySet) { + return new UnmodifiableEntrySet(Collections.unmodifiableSet(entrySet)); + } + + static Map.Entry unmodifiableEntry(final Map.Entry entry) { + Preconditions.checkNotNull(entry); + return new AbstractMapEntry(){ + + @Override + public K getKey() { + return entry.getKey(); + } + + @Override + public V getValue() { + return entry.getValue(); + } + }; + } + + @Beta + public static Converter asConverter(BiMap bimap) { + return new BiMapConverter(bimap); + } + + public static BiMap synchronizedBiMap(BiMap bimap) { + return Synchronized.biMap(bimap, null); + } + + public static BiMap unmodifiableBiMap(BiMap bimap) { + return new UnmodifiableBiMap(bimap, null); + } + + public static Map transformValues(Map fromMap, Function function) { + return Maps.transformEntries(fromMap, Maps.asEntryTransformer(function)); + } + + public static SortedMap transformValues(SortedMap fromMap, Function function) { + return Maps.transformEntries(fromMap, Maps.asEntryTransformer(function)); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap transformValues(NavigableMap fromMap, Function function) { + return Maps.transformEntries(fromMap, Maps.asEntryTransformer(function)); + } + + public static Map transformEntries(Map fromMap, EntryTransformer transformer) { + if (fromMap instanceof SortedMap) { + return Maps.transformEntries((SortedMap)fromMap, transformer); + } + return new TransformedEntriesMap(fromMap, transformer); + } + + public static SortedMap transformEntries(SortedMap fromMap, EntryTransformer transformer) { + return Platform.mapsTransformEntriesSortedMap(fromMap, transformer); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap transformEntries(NavigableMap fromMap, EntryTransformer transformer) { + return new TransformedEntriesNavigableMap(fromMap, transformer); + } + + static SortedMap transformEntriesIgnoreNavigable(SortedMap fromMap, EntryTransformer transformer) { + return new TransformedEntriesSortedMap(fromMap, transformer); + } + + static EntryTransformer asEntryTransformer(final Function function) { + Preconditions.checkNotNull(function); + return new EntryTransformer(){ + + @Override + public V2 transformEntry(K key, V1 value) { + return function.apply(value); + } + }; + } + + static Function asValueToValueFunction(final EntryTransformer transformer, final K key) { + Preconditions.checkNotNull(transformer); + return new Function(){ + + @Override + public V2 apply(@Nullable V1 v1) { + return transformer.transformEntry(key, v1); + } + }; + } + + static Function, V2> asEntryToValueFunction(final EntryTransformer transformer) { + Preconditions.checkNotNull(transformer); + return new Function, V2>(){ + + @Override + public V2 apply(Map.Entry entry) { + return transformer.transformEntry(entry.getKey(), entry.getValue()); + } + }; + } + + static Map.Entry transformEntry(final EntryTransformer transformer, final Map.Entry entry) { + Preconditions.checkNotNull(transformer); + Preconditions.checkNotNull(entry); + return new AbstractMapEntry(){ + + @Override + public K getKey() { + return entry.getKey(); + } + + @Override + public V2 getValue() { + return transformer.transformEntry(entry.getKey(), entry.getValue()); + } + }; + } + + static Function, Map.Entry> asEntryToEntryFunction(final EntryTransformer transformer) { + Preconditions.checkNotNull(transformer); + return new Function, Map.Entry>(){ + + @Override + public Map.Entry apply(Map.Entry entry) { + return Maps.transformEntry(transformer, entry); + } + }; + } + + static Predicate> keyPredicateOnEntries(Predicate keyPredicate) { + return Predicates.compose(keyPredicate, Maps.keyFunction()); + } + + static Predicate> valuePredicateOnEntries(Predicate valuePredicate) { + return Predicates.compose(valuePredicate, Maps.valueFunction()); + } + + public static Map filterKeys(Map unfiltered, Predicate keyPredicate) { + if (unfiltered instanceof SortedMap) { + return Maps.filterKeys((SortedMap)unfiltered, keyPredicate); + } + if (unfiltered instanceof BiMap) { + return Maps.filterKeys((BiMap)unfiltered, keyPredicate); + } + Preconditions.checkNotNull(keyPredicate); + Predicate> entryPredicate = Maps.keyPredicateOnEntries(keyPredicate); + return unfiltered instanceof AbstractFilteredMap ? Maps.filterFiltered((AbstractFilteredMap)unfiltered, entryPredicate) : new FilteredKeyMap(Preconditions.checkNotNull(unfiltered), keyPredicate, entryPredicate); + } + + public static SortedMap filterKeys(SortedMap unfiltered, Predicate keyPredicate) { + return Maps.filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap filterKeys(NavigableMap unfiltered, Predicate keyPredicate) { + return Maps.filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); + } + + public static BiMap filterKeys(BiMap unfiltered, Predicate keyPredicate) { + Preconditions.checkNotNull(keyPredicate); + return Maps.filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); + } + + public static Map filterValues(Map unfiltered, Predicate valuePredicate) { + if (unfiltered instanceof SortedMap) { + return Maps.filterValues((SortedMap)unfiltered, valuePredicate); + } + if (unfiltered instanceof BiMap) { + return Maps.filterValues((BiMap)unfiltered, valuePredicate); + } + return Maps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + public static SortedMap filterValues(SortedMap unfiltered, Predicate valuePredicate) { + return Maps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap filterValues(NavigableMap unfiltered, Predicate valuePredicate) { + return Maps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + public static BiMap filterValues(BiMap unfiltered, Predicate valuePredicate) { + return Maps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + public static Map filterEntries(Map unfiltered, Predicate> entryPredicate) { + if (unfiltered instanceof SortedMap) { + return Maps.filterEntries((SortedMap)unfiltered, entryPredicate); + } + if (unfiltered instanceof BiMap) { + return Maps.filterEntries((BiMap)unfiltered, entryPredicate); + } + Preconditions.checkNotNull(entryPredicate); + return unfiltered instanceof AbstractFilteredMap ? Maps.filterFiltered((AbstractFilteredMap)unfiltered, entryPredicate) : new FilteredEntryMap(Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + public static SortedMap filterEntries(SortedMap unfiltered, Predicate> entryPredicate) { + return Platform.mapsFilterSortedMap(unfiltered, entryPredicate); + } + + static SortedMap filterSortedIgnoreNavigable(SortedMap unfiltered, Predicate> entryPredicate) { + Preconditions.checkNotNull(entryPredicate); + return unfiltered instanceof FilteredEntrySortedMap ? Maps.filterFiltered((FilteredEntrySortedMap)unfiltered, entryPredicate) : new FilteredEntrySortedMap(Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap filterEntries(NavigableMap unfiltered, Predicate> entryPredicate) { + Preconditions.checkNotNull(entryPredicate); + return unfiltered instanceof FilteredEntryNavigableMap ? Maps.filterFiltered((FilteredEntryNavigableMap)unfiltered, entryPredicate) : new FilteredEntryNavigableMap(Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + public static BiMap filterEntries(BiMap unfiltered, Predicate> entryPredicate) { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(entryPredicate); + return unfiltered instanceof FilteredEntryBiMap ? Maps.filterFiltered((FilteredEntryBiMap)unfiltered, entryPredicate) : new FilteredEntryBiMap(unfiltered, entryPredicate); + } + + private static Map filterFiltered(AbstractFilteredMap map, Predicate> entryPredicate) { + return new FilteredEntryMap(map.unfiltered, Predicates.and(map.predicate, entryPredicate)); + } + + private static SortedMap filterFiltered(FilteredEntrySortedMap map, Predicate> entryPredicate) { + Predicate> predicate = Predicates.and(map.predicate, entryPredicate); + return new FilteredEntrySortedMap(map.sortedMap(), predicate); + } + + @GwtIncompatible(value="NavigableMap") + private static NavigableMap filterFiltered(FilteredEntryNavigableMap map, Predicate> entryPredicate) { + Predicate> predicate = Predicates.and(((FilteredEntryNavigableMap)map).entryPredicate, entryPredicate); + return new FilteredEntryNavigableMap(((FilteredEntryNavigableMap)map).unfiltered, predicate); + } + + private static BiMap filterFiltered(FilteredEntryBiMap map, Predicate> entryPredicate) { + Predicate> predicate = Predicates.and(map.predicate, entryPredicate); + return new FilteredEntryBiMap(map.unfiltered(), predicate); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap unmodifiableNavigableMap(NavigableMap map) { + Preconditions.checkNotNull(map); + if (map instanceof UnmodifiableNavigableMap) { + return map; + } + return new UnmodifiableNavigableMap(map); + } + + @Nullable + private static Map.Entry unmodifiableOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : Maps.unmodifiableEntry(entry); + } + + @GwtIncompatible(value="NavigableMap") + public static NavigableMap synchronizedNavigableMap(NavigableMap navigableMap) { + return Synchronized.navigableMap(navigableMap); + } + + static V safeGet(Map map, @Nullable Object key) { + Preconditions.checkNotNull(map); + try { + return map.get(key); + } + catch (ClassCastException e) { + return null; + } + catch (NullPointerException e) { + return null; + } + } + + static boolean safeContainsKey(Map map, Object key) { + Preconditions.checkNotNull(map); + try { + return map.containsKey(key); + } + catch (ClassCastException e) { + return false; + } + catch (NullPointerException e) { + return false; + } + } + + static V safeRemove(Map map, Object key) { + Preconditions.checkNotNull(map); + try { + return map.remove(key); + } + catch (ClassCastException e) { + return null; + } + catch (NullPointerException e) { + return null; + } + } + + static boolean containsKeyImpl(Map map, @Nullable Object key) { + return Iterators.contains(Maps.keyIterator(map.entrySet().iterator()), key); + } + + static boolean containsValueImpl(Map map, @Nullable Object value) { + return Iterators.contains(Maps.valueIterator(map.entrySet().iterator()), value); + } + + static boolean containsEntryImpl(Collection> c, Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + return c.contains(Maps.unmodifiableEntry((Map.Entry)o)); + } + + static boolean removeEntryImpl(Collection> c, Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + return c.remove(Maps.unmodifiableEntry((Map.Entry)o)); + } + + static boolean equalsImpl(Map map, Object object) { + if (map == object) { + return true; + } + if (object instanceof Map) { + Map o = (Map)object; + return map.entrySet().equals(o.entrySet()); + } + return false; + } + + static String toStringImpl(Map map) { + StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{'); + STANDARD_JOINER.appendTo(sb, map); + return sb.append('}').toString(); + } + + static void putAllImpl(Map self, Map map) { + for (Map.Entry entry : map.entrySet()) { + self.put(entry.getKey(), entry.getValue()); + } + } + + @Nullable + static K keyOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : (K)entry.getKey(); + } + + @Nullable + static V valueOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : (V)entry.getValue(); + } + + @GwtIncompatible(value="NavigableMap") + static abstract class DescendingMap + extends ForwardingMap + implements NavigableMap { + private transient Comparator comparator; + private transient Set> entrySet; + private transient NavigableSet navigableKeySet; + + DescendingMap() { + } + + abstract NavigableMap forward(); + + @Override + protected final Map delegate() { + return this.forward(); + } + + @Override + public Comparator comparator() { + Comparator result = this.comparator; + if (result == null) { + Comparator forwardCmp = this.forward().comparator(); + if (forwardCmp == null) { + forwardCmp = Ordering.natural(); + } + result = this.comparator = DescendingMap.reverse(forwardCmp); + } + return result; + } + + private static Ordering reverse(Comparator forward) { + return Ordering.from(forward).reverse(); + } + + @Override + public K firstKey() { + return this.forward().lastKey(); + } + + @Override + public K lastKey() { + return this.forward().firstKey(); + } + + @Override + public Map.Entry lowerEntry(K key) { + return this.forward().higherEntry(key); + } + + @Override + public K lowerKey(K key) { + return this.forward().higherKey(key); + } + + @Override + public Map.Entry floorEntry(K key) { + return this.forward().ceilingEntry(key); + } + + @Override + public K floorKey(K key) { + return this.forward().ceilingKey(key); + } + + @Override + public Map.Entry ceilingEntry(K key) { + return this.forward().floorEntry(key); + } + + @Override + public K ceilingKey(K key) { + return this.forward().floorKey(key); + } + + @Override + public Map.Entry higherEntry(K key) { + return this.forward().lowerEntry(key); + } + + @Override + public K higherKey(K key) { + return this.forward().lowerKey(key); + } + + @Override + public Map.Entry firstEntry() { + return this.forward().lastEntry(); + } + + @Override + public Map.Entry lastEntry() { + return this.forward().firstEntry(); + } + + @Override + public Map.Entry pollFirstEntry() { + return this.forward().pollLastEntry(); + } + + @Override + public Map.Entry pollLastEntry() { + return this.forward().pollFirstEntry(); + } + + @Override + public NavigableMap descendingMap() { + return this.forward(); + } + + @Override + public Set> entrySet() { + Set> result = this.entrySet; + return result == null ? (this.entrySet = this.createEntrySet()) : result; + } + + abstract Iterator> entryIterator(); + + Set> createEntrySet() { + return new EntrySet(){ + + @Override + Map map() { + return DescendingMap.this; + } + + @Override + public Iterator> iterator() { + return DescendingMap.this.entryIterator(); + } + }; + } + + @Override + public Set keySet() { + return this.navigableKeySet(); + } + + @Override + public NavigableSet navigableKeySet() { + NavigableSet result = this.navigableKeySet; + return result == null ? (this.navigableKeySet = new NavigableKeySet(this)) : result; + } + + @Override + public NavigableSet descendingKeySet() { + return this.forward().navigableKeySet(); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return this.forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap(); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return this.forward().tailMap(toKey, inclusive).descendingMap(); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return this.forward().headMap(fromKey, inclusive).descendingMap(); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public SortedMap headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public SortedMap tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Override + public Collection values() { + return new Values(this); + } + + @Override + public String toString() { + return this.standardToString(); + } + } + + static abstract class EntrySet + extends Sets.ImprovedAbstractSet> { + EntrySet() { + } + + abstract Map map(); + + @Override + public int size() { + return this.map().size(); + } + + @Override + public void clear() { + this.map().clear(); + } + + @Override + public boolean contains(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)o; + Object key = entry.getKey(); + V value = Maps.safeGet(this.map(), key); + return Objects.equal(value, entry.getValue()) && (value != null || this.map().containsKey(key)); + } + return false; + } + + @Override + public boolean isEmpty() { + return this.map().isEmpty(); + } + + @Override + public boolean remove(Object o) { + if (this.contains(o)) { + Map.Entry entry = (Map.Entry)o; + return this.map().keySet().remove(entry.getKey()); + } + return false; + } + + @Override + public boolean removeAll(Collection c) { + try { + return super.removeAll(Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) { + return Sets.removeAllImpl(this, c.iterator()); + } + } + + @Override + public boolean retainAll(Collection c) { + try { + return super.retainAll(Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) { + HashSet keys = Sets.newHashSetWithExpectedSize(c.size()); + for (Object o : c) { + if (!this.contains(o)) continue; + Map.Entry entry = (Map.Entry)o; + keys.add(entry.getKey()); + } + return this.map().keySet().retainAll(keys); + } + } + } + + static class Values + extends AbstractCollection { + final Map map; + + Values(Map map) { + this.map = Preconditions.checkNotNull(map); + } + + final Map map() { + return this.map; + } + + @Override + public Iterator iterator() { + return Maps.valueIterator(this.map().entrySet().iterator()); + } + + @Override + public boolean remove(Object o) { + try { + return super.remove(o); + } + catch (UnsupportedOperationException e) { + for (Map.Entry entry : this.map().entrySet()) { + if (!Objects.equal(o, entry.getValue())) continue; + this.map().remove(entry.getKey()); + return true; + } + return false; + } + } + + @Override + public boolean removeAll(Collection c) { + try { + return super.removeAll(Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) { + HashSet toRemove = Sets.newHashSet(); + for (Map.Entry entry : this.map().entrySet()) { + if (!c.contains(entry.getValue())) continue; + toRemove.add(entry.getKey()); + } + return this.map().keySet().removeAll(toRemove); + } + } + + @Override + public boolean retainAll(Collection c) { + try { + return super.retainAll(Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) { + HashSet toRetain = Sets.newHashSet(); + for (Map.Entry entry : this.map().entrySet()) { + if (!c.contains(entry.getValue())) continue; + toRetain.add(entry.getKey()); + } + return this.map().keySet().retainAll(toRetain); + } + } + + @Override + public int size() { + return this.map().size(); + } + + @Override + public boolean isEmpty() { + return this.map().isEmpty(); + } + + @Override + public boolean contains(@Nullable Object o) { + return this.map().containsValue(o); + } + + @Override + public void clear() { + this.map().clear(); + } + } + + @GwtIncompatible(value="NavigableMap") + static class NavigableKeySet + extends SortedKeySet + implements NavigableSet { + NavigableKeySet(NavigableMap map) { + super(map); + } + + @Override + NavigableMap map() { + return (NavigableMap)this.map; + } + + @Override + public K lower(K e) { + return this.map().lowerKey(e); + } + + @Override + public K floor(K e) { + return this.map().floorKey(e); + } + + @Override + public K ceiling(K e) { + return this.map().ceilingKey(e); + } + + @Override + public K higher(K e) { + return this.map().higherKey(e); + } + + @Override + public K pollFirst() { + return Maps.keyOrNull(this.map().pollFirstEntry()); + } + + @Override + public K pollLast() { + return Maps.keyOrNull(this.map().pollLastEntry()); + } + + @Override + public NavigableSet descendingSet() { + return this.map().descendingKeySet(); + } + + @Override + public Iterator descendingIterator() { + return this.descendingSet().iterator(); + } + + @Override + public NavigableSet subSet(K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) { + return this.map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet(); + } + + @Override + public NavigableSet headSet(K toElement, boolean inclusive) { + return this.map().headMap(toElement, inclusive).navigableKeySet(); + } + + @Override + public NavigableSet tailSet(K fromElement, boolean inclusive) { + return this.map().tailMap(fromElement, inclusive).navigableKeySet(); + } + + @Override + public SortedSet subSet(K fromElement, K toElement) { + return this.subSet(fromElement, true, toElement, false); + } + + @Override + public SortedSet headSet(K toElement) { + return this.headSet(toElement, false); + } + + @Override + public SortedSet tailSet(K fromElement) { + return this.tailSet(fromElement, true); + } + } + + static class SortedKeySet + extends KeySet + implements SortedSet { + SortedKeySet(SortedMap map) { + super(map); + } + + @Override + SortedMap map() { + return (SortedMap)super.map(); + } + + @Override + public Comparator comparator() { + return this.map().comparator(); + } + + @Override + public SortedSet subSet(K fromElement, K toElement) { + return new SortedKeySet(this.map().subMap(fromElement, toElement)); + } + + @Override + public SortedSet headSet(K toElement) { + return new SortedKeySet(this.map().headMap(toElement)); + } + + @Override + public SortedSet tailSet(K fromElement) { + return new SortedKeySet(this.map().tailMap(fromElement)); + } + + @Override + public K first() { + return this.map().firstKey(); + } + + @Override + public K last() { + return this.map().lastKey(); + } + } + + static class KeySet + extends Sets.ImprovedAbstractSet { + final Map map; + + KeySet(Map map) { + this.map = Preconditions.checkNotNull(map); + } + + Map map() { + return this.map; + } + + @Override + public Iterator iterator() { + return Maps.keyIterator(this.map().entrySet().iterator()); + } + + @Override + public int size() { + return this.map().size(); + } + + @Override + public boolean isEmpty() { + return this.map().isEmpty(); + } + + @Override + public boolean contains(Object o) { + return this.map().containsKey(o); + } + + @Override + public boolean remove(Object o) { + if (this.contains(o)) { + this.map().remove(o); + return true; + } + return false; + } + + @Override + public void clear() { + this.map().clear(); + } + } + + @GwtCompatible + static abstract class ImprovedAbstractMap + extends AbstractMap { + private transient Set> entrySet; + private transient Set keySet; + private transient Collection values; + + ImprovedAbstractMap() { + } + + abstract Set> createEntrySet(); + + @Override + public Set> entrySet() { + Set> result = this.entrySet; + return result == null ? (this.entrySet = this.createEntrySet()) : result; + } + + @Override + public Set keySet() { + Set result = this.keySet; + return result == null ? (this.keySet = this.createKeySet()) : result; + } + + Set createKeySet() { + return new KeySet(this); + } + + @Override + public Collection values() { + Collection result = this.values; + return result == null ? (this.values = this.createValues()) : result; + } + + Collection createValues() { + return new Values(this); + } + } + + @GwtIncompatible(value="NavigableMap") + static class UnmodifiableNavigableMap + extends ForwardingSortedMap + implements NavigableMap, + Serializable { + private final NavigableMap delegate; + private transient UnmodifiableNavigableMap descendingMap; + + UnmodifiableNavigableMap(NavigableMap delegate) { + this.delegate = delegate; + } + + UnmodifiableNavigableMap(NavigableMap delegate, UnmodifiableNavigableMap descendingMap) { + this.delegate = delegate; + this.descendingMap = descendingMap; + } + + @Override + protected SortedMap delegate() { + return Collections.unmodifiableSortedMap(this.delegate); + } + + @Override + public Map.Entry lowerEntry(K key) { + return Maps.unmodifiableOrNull(this.delegate.lowerEntry(key)); + } + + @Override + public K lowerKey(K key) { + return this.delegate.lowerKey(key); + } + + @Override + public Map.Entry floorEntry(K key) { + return Maps.unmodifiableOrNull(this.delegate.floorEntry(key)); + } + + @Override + public K floorKey(K key) { + return this.delegate.floorKey(key); + } + + @Override + public Map.Entry ceilingEntry(K key) { + return Maps.unmodifiableOrNull(this.delegate.ceilingEntry(key)); + } + + @Override + public K ceilingKey(K key) { + return this.delegate.ceilingKey(key); + } + + @Override + public Map.Entry higherEntry(K key) { + return Maps.unmodifiableOrNull(this.delegate.higherEntry(key)); + } + + @Override + public K higherKey(K key) { + return this.delegate.higherKey(key); + } + + @Override + public Map.Entry firstEntry() { + return Maps.unmodifiableOrNull(this.delegate.firstEntry()); + } + + @Override + public Map.Entry lastEntry() { + return Maps.unmodifiableOrNull(this.delegate.lastEntry()); + } + + @Override + public final Map.Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public final Map.Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public NavigableMap descendingMap() { + UnmodifiableNavigableMap result = this.descendingMap; + return result == null ? (this.descendingMap = new UnmodifiableNavigableMap(this.delegate.descendingMap(), this)) : result; + } + + @Override + public Set keySet() { + return this.navigableKeySet(); + } + + @Override + public NavigableSet navigableKeySet() { + return Sets.unmodifiableNavigableSet(this.delegate.navigableKeySet()); + } + + @Override + public NavigableSet descendingKeySet() { + return Sets.unmodifiableNavigableSet(this.delegate.descendingKeySet()); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public SortedMap headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public SortedMap tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return Maps.unmodifiableNavigableMap(this.delegate.subMap(fromKey, fromInclusive, toKey, toInclusive)); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return Maps.unmodifiableNavigableMap(this.delegate.headMap(toKey, inclusive)); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return Maps.unmodifiableNavigableMap(this.delegate.tailMap(fromKey, inclusive)); + } + } + + static final class FilteredEntryBiMap + extends FilteredEntryMap + implements BiMap { + private final BiMap inverse; + + private static Predicate> inversePredicate(final Predicate> forwardPredicate) { + return new Predicate>(){ + + @Override + public boolean apply(Map.Entry input) { + return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey())); + } + }; + } + + FilteredEntryBiMap(BiMap delegate, Predicate> predicate) { + super(delegate, predicate); + this.inverse = new FilteredEntryBiMap(delegate.inverse(), FilteredEntryBiMap.inversePredicate(predicate), this); + } + + private FilteredEntryBiMap(BiMap delegate, Predicate> predicate, BiMap inverse) { + super(delegate, predicate); + this.inverse = inverse; + } + + BiMap unfiltered() { + return (BiMap)this.unfiltered; + } + + @Override + public V forcePut(@Nullable K key, @Nullable V value) { + Preconditions.checkArgument(this.apply(key, value)); + return this.unfiltered().forcePut(key, value); + } + + @Override + public BiMap inverse() { + return this.inverse; + } + + @Override + public Set values() { + return this.inverse.keySet(); + } + } + + @GwtIncompatible(value="NavigableMap") + private static class FilteredEntryNavigableMap + extends AbstractNavigableMap { + private final NavigableMap unfiltered; + private final Predicate> entryPredicate; + private final Map filteredDelegate; + + FilteredEntryNavigableMap(NavigableMap unfiltered, Predicate> entryPredicate) { + this.unfiltered = Preconditions.checkNotNull(unfiltered); + this.entryPredicate = entryPredicate; + this.filteredDelegate = new FilteredEntryMap(unfiltered, entryPredicate); + } + + @Override + public Comparator comparator() { + return this.unfiltered.comparator(); + } + + @Override + public NavigableSet navigableKeySet() { + return new NavigableKeySet(this){ + + @Override + public boolean removeAll(Collection c) { + return Iterators.removeIf(FilteredEntryNavigableMap.this.unfiltered.entrySet().iterator(), Predicates.and(FilteredEntryNavigableMap.this.entryPredicate, Maps.keyPredicateOnEntries(Predicates.in(c)))); + } + + @Override + public boolean retainAll(Collection c) { + return Iterators.removeIf(FilteredEntryNavigableMap.this.unfiltered.entrySet().iterator(), Predicates.and(FilteredEntryNavigableMap.this.entryPredicate, Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c))))); + } + }; + } + + @Override + public Collection values() { + return new FilteredMapValues(this, this.unfiltered, this.entryPredicate); + } + + @Override + Iterator> entryIterator() { + return Iterators.filter(this.unfiltered.entrySet().iterator(), this.entryPredicate); + } + + @Override + Iterator> descendingEntryIterator() { + return Iterators.filter(this.unfiltered.descendingMap().entrySet().iterator(), this.entryPredicate); + } + + @Override + public int size() { + return this.filteredDelegate.size(); + } + + @Override + public boolean isEmpty() { + return !Iterables.any(this.unfiltered.entrySet(), this.entryPredicate); + } + + @Override + @Nullable + public V get(@Nullable Object key) { + return this.filteredDelegate.get(key); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.filteredDelegate.containsKey(key); + } + + @Override + public V put(K key, V value) { + return this.filteredDelegate.put(key, value); + } + + @Override + public V remove(@Nullable Object key) { + return this.filteredDelegate.remove(key); + } + + @Override + public void putAll(Map m) { + this.filteredDelegate.putAll(m); + } + + @Override + public void clear() { + this.filteredDelegate.clear(); + } + + @Override + public Set> entrySet() { + return this.filteredDelegate.entrySet(); + } + + @Override + public Map.Entry pollFirstEntry() { + return Iterables.removeFirstMatching(this.unfiltered.entrySet(), this.entryPredicate); + } + + @Override + public Map.Entry pollLastEntry() { + return Iterables.removeFirstMatching(this.unfiltered.descendingMap().entrySet(), this.entryPredicate); + } + + @Override + public NavigableMap descendingMap() { + return Maps.filterEntries(this.unfiltered.descendingMap(), this.entryPredicate); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return Maps.filterEntries(this.unfiltered.subMap(fromKey, fromInclusive, toKey, toInclusive), this.entryPredicate); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return Maps.filterEntries(this.unfiltered.headMap(toKey, inclusive), this.entryPredicate); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return Maps.filterEntries(this.unfiltered.tailMap(fromKey, inclusive), this.entryPredicate); + } + } + + private static class FilteredEntrySortedMap + extends FilteredEntryMap + implements SortedMap { + FilteredEntrySortedMap(SortedMap unfiltered, Predicate> entryPredicate) { + super(unfiltered, entryPredicate); + } + + SortedMap sortedMap() { + return (SortedMap)this.unfiltered; + } + + @Override + public SortedSet keySet() { + return (SortedSet)super.keySet(); + } + + @Override + SortedSet createKeySet() { + return new SortedKeySet(); + } + + @Override + public Comparator comparator() { + return this.sortedMap().comparator(); + } + + @Override + public K firstKey() { + return (K)this.keySet().iterator().next(); + } + + @Override + public K lastKey() { + SortedMap headMap = this.sortedMap(); + K key; + while (!this.apply(key = headMap.lastKey(), this.unfiltered.get(key))) { + headMap = this.sortedMap().headMap(key); + } + return key; + } + + @Override + public SortedMap headMap(K toKey) { + return new FilteredEntrySortedMap(this.sortedMap().headMap(toKey), this.predicate); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return new FilteredEntrySortedMap(this.sortedMap().subMap(fromKey, toKey), this.predicate); + } + + @Override + public SortedMap tailMap(K fromKey) { + return new FilteredEntrySortedMap(this.sortedMap().tailMap(fromKey), this.predicate); + } + + class SortedKeySet + extends FilteredEntryMap.KeySet + implements SortedSet { + SortedKeySet() { + } + + @Override + public Comparator comparator() { + return FilteredEntrySortedMap.this.sortedMap().comparator(); + } + + @Override + public SortedSet subSet(K fromElement, K toElement) { + return (SortedSet)FilteredEntrySortedMap.this.subMap(fromElement, toElement).keySet(); + } + + @Override + public SortedSet headSet(K toElement) { + return (SortedSet)FilteredEntrySortedMap.this.headMap(toElement).keySet(); + } + + @Override + public SortedSet tailSet(K fromElement) { + return (SortedSet)FilteredEntrySortedMap.this.tailMap(fromElement).keySet(); + } + + @Override + public K first() { + return FilteredEntrySortedMap.this.firstKey(); + } + + @Override + public K last() { + return FilteredEntrySortedMap.this.lastKey(); + } + } + } + + static class FilteredEntryMap + extends AbstractFilteredMap { + final Set> filteredEntrySet; + + FilteredEntryMap(Map unfiltered, Predicate> entryPredicate) { + super(unfiltered, entryPredicate); + this.filteredEntrySet = Sets.filter(unfiltered.entrySet(), this.predicate); + } + + @Override + protected Set> createEntrySet() { + return new EntrySet(); + } + + @Override + Set createKeySet() { + return new KeySet(); + } + + class KeySet + extends com.google.common.collect.Maps$KeySet { + KeySet() { + super(FilteredEntryMap.this); + } + + @Override + public boolean remove(Object o) { + if (FilteredEntryMap.this.containsKey(o)) { + FilteredEntryMap.this.unfiltered.remove(o); + return true; + } + return false; + } + + @Override + private boolean removeIf(Predicate keyPredicate) { + return Iterables.removeIf(FilteredEntryMap.this.unfiltered.entrySet(), Predicates.and(FilteredEntryMap.this.predicate, Maps.keyPredicateOnEntries(keyPredicate))); + } + + @Override + public boolean removeAll(Collection c) { + return this.removeIf(Predicates.in(c)); + } + + @Override + public boolean retainAll(Collection c) { + return this.removeIf(Predicates.not(Predicates.in(c))); + } + + @Override + public Object[] toArray() { + return Lists.newArrayList(this.iterator()).toArray(); + } + + @Override + public T[] toArray(T[] array) { + return Lists.newArrayList(this.iterator()).toArray(array); + } + } + + private class EntrySet + extends ForwardingSet> { + private EntrySet() { + } + + @Override + protected Set> delegate() { + return FilteredEntryMap.this.filteredEntrySet; + } + + @Override + public Iterator> iterator() { + return new TransformedIterator, Map.Entry>(FilteredEntryMap.this.filteredEntrySet.iterator()){ + + @Override + Map.Entry transform(final Map.Entry entry) { + return new ForwardingMapEntry(){ + + @Override + protected Map.Entry delegate() { + return entry; + } + + @Override + public V setValue(V newValue) { + Preconditions.checkArgument(FilteredEntryMap.this.apply(this.getKey(), newValue)); + return super.setValue(newValue); + } + }; + } + }; + } + } + } + + private static class FilteredKeyMap + extends AbstractFilteredMap { + Predicate keyPredicate; + + FilteredKeyMap(Map unfiltered, Predicate keyPredicate, Predicate> entryPredicate) { + super(unfiltered, entryPredicate); + this.keyPredicate = keyPredicate; + } + + @Override + protected Set> createEntrySet() { + return Sets.filter(this.unfiltered.entrySet(), this.predicate); + } + + @Override + Set createKeySet() { + return Sets.filter(this.unfiltered.keySet(), this.keyPredicate); + } + + @Override + public boolean containsKey(Object key) { + return this.unfiltered.containsKey(key) && this.keyPredicate.apply(key); + } + } + + private static final class FilteredMapValues + extends Values { + Map unfiltered; + Predicate> predicate; + + FilteredMapValues(Map filteredMap, Map unfiltered, Predicate> predicate) { + super(filteredMap); + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + @Override + public boolean remove(Object o) { + return Iterables.removeFirstMatching(this.unfiltered.entrySet(), Predicates.and(this.predicate, Maps.valuePredicateOnEntries(Predicates.equalTo(o)))) != null; + } + + @Override + private boolean removeIf(Predicate valuePredicate) { + return Iterables.removeIf(this.unfiltered.entrySet(), Predicates.and(this.predicate, Maps.valuePredicateOnEntries(valuePredicate))); + } + + @Override + public boolean removeAll(Collection collection) { + return this.removeIf(Predicates.in(collection)); + } + + @Override + public boolean retainAll(Collection collection) { + return this.removeIf(Predicates.not(Predicates.in(collection))); + } + + @Override + public Object[] toArray() { + return Lists.newArrayList(this.iterator()).toArray(); + } + + @Override + public T[] toArray(T[] array) { + return Lists.newArrayList(this.iterator()).toArray(array); + } + } + + private static abstract class AbstractFilteredMap + extends ImprovedAbstractMap { + final Map unfiltered; + final Predicate> predicate; + + AbstractFilteredMap(Map unfiltered, Predicate> predicate) { + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + boolean apply(@Nullable Object key, @Nullable V value) { + Object k = key; + return this.predicate.apply(Maps.immutableEntry(k, value)); + } + + @Override + public V put(K key, V value) { + Preconditions.checkArgument(this.apply(key, value)); + return this.unfiltered.put(key, value); + } + + @Override + public void putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + Preconditions.checkArgument(this.apply(entry.getKey(), entry.getValue())); + } + this.unfiltered.putAll(map); + } + + @Override + public boolean containsKey(Object key) { + return this.unfiltered.containsKey(key) && this.apply(key, this.unfiltered.get(key)); + } + + @Override + public V get(Object key) { + V value = this.unfiltered.get(key); + return value != null && this.apply(key, value) ? (V)value : null; + } + + @Override + public boolean isEmpty() { + return this.entrySet().isEmpty(); + } + + @Override + public V remove(Object key) { + return this.containsKey(key) ? (V)this.unfiltered.remove(key) : null; + } + + @Override + Collection createValues() { + return new FilteredMapValues(this, this.unfiltered, this.predicate); + } + } + + @GwtIncompatible(value="NavigableMap") + private static class TransformedEntriesNavigableMap + extends TransformedEntriesSortedMap + implements NavigableMap { + TransformedEntriesNavigableMap(NavigableMap fromMap, EntryTransformer transformer) { + super(fromMap, transformer); + } + + @Override + public Map.Entry ceilingEntry(K key) { + return this.transformEntry(this.fromMap().ceilingEntry(key)); + } + + @Override + public K ceilingKey(K key) { + return this.fromMap().ceilingKey(key); + } + + @Override + public NavigableSet descendingKeySet() { + return this.fromMap().descendingKeySet(); + } + + @Override + public NavigableMap descendingMap() { + return Maps.transformEntries(this.fromMap().descendingMap(), this.transformer); + } + + @Override + public Map.Entry firstEntry() { + return this.transformEntry(this.fromMap().firstEntry()); + } + + @Override + public Map.Entry floorEntry(K key) { + return this.transformEntry(this.fromMap().floorEntry(key)); + } + + @Override + public K floorKey(K key) { + return this.fromMap().floorKey(key); + } + + @Override + public NavigableMap headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return Maps.transformEntries(this.fromMap().headMap(toKey, inclusive), this.transformer); + } + + @Override + public Map.Entry higherEntry(K key) { + return this.transformEntry(this.fromMap().higherEntry(key)); + } + + @Override + public K higherKey(K key) { + return this.fromMap().higherKey(key); + } + + @Override + public Map.Entry lastEntry() { + return this.transformEntry(this.fromMap().lastEntry()); + } + + @Override + public Map.Entry lowerEntry(K key) { + return this.transformEntry(this.fromMap().lowerEntry(key)); + } + + @Override + public K lowerKey(K key) { + return this.fromMap().lowerKey(key); + } + + @Override + public NavigableSet navigableKeySet() { + return this.fromMap().navigableKeySet(); + } + + @Override + public Map.Entry pollFirstEntry() { + return this.transformEntry(this.fromMap().pollFirstEntry()); + } + + @Override + public Map.Entry pollLastEntry() { + return this.transformEntry(this.fromMap().pollLastEntry()); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return Maps.transformEntries(this.fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), this.transformer); + } + + @Override + public NavigableMap subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public NavigableMap tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return Maps.transformEntries(this.fromMap().tailMap(fromKey, inclusive), this.transformer); + } + + @Nullable + private Map.Entry transformEntry(@Nullable Map.Entry entry) { + return entry == null ? null : Maps.transformEntry(this.transformer, entry); + } + + @Override + protected NavigableMap fromMap() { + return (NavigableMap)super.fromMap(); + } + } + + static class TransformedEntriesSortedMap + extends TransformedEntriesMap + implements SortedMap { + protected SortedMap fromMap() { + return (SortedMap)this.fromMap; + } + + TransformedEntriesSortedMap(SortedMap fromMap, EntryTransformer transformer) { + super(fromMap, transformer); + } + + @Override + public Comparator comparator() { + return this.fromMap().comparator(); + } + + @Override + public K firstKey() { + return this.fromMap().firstKey(); + } + + @Override + public SortedMap headMap(K toKey) { + return Maps.transformEntries(this.fromMap().headMap(toKey), this.transformer); + } + + @Override + public K lastKey() { + return this.fromMap().lastKey(); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return Maps.transformEntries(this.fromMap().subMap(fromKey, toKey), this.transformer); + } + + @Override + public SortedMap tailMap(K fromKey) { + return Maps.transformEntries(this.fromMap().tailMap(fromKey), this.transformer); + } + } + + static class TransformedEntriesMap + extends ImprovedAbstractMap { + final Map fromMap; + final EntryTransformer transformer; + + TransformedEntriesMap(Map fromMap, EntryTransformer transformer) { + this.fromMap = Preconditions.checkNotNull(fromMap); + this.transformer = Preconditions.checkNotNull(transformer); + } + + @Override + public int size() { + return this.fromMap.size(); + } + + @Override + public boolean containsKey(Object key) { + return this.fromMap.containsKey(key); + } + + @Override + public V2 get(Object key) { + V1 value = this.fromMap.get(key); + return (V2)(value != null || this.fromMap.containsKey(key) ? this.transformer.transformEntry(key, value) : null); + } + + @Override + public V2 remove(Object key) { + return this.fromMap.containsKey(key) ? (V2)this.transformer.transformEntry((K)key, (V1)this.fromMap.remove(key)) : null; + } + + @Override + public void clear() { + this.fromMap.clear(); + } + + @Override + public Set keySet() { + return this.fromMap.keySet(); + } + + @Override + protected Set> createEntrySet() { + return new EntrySet(){ + + @Override + Map map() { + return TransformedEntriesMap.this; + } + + @Override + public Iterator> iterator() { + return Iterators.transform(TransformedEntriesMap.this.fromMap.entrySet().iterator(), Maps.asEntryToEntryFunction(TransformedEntriesMap.this.transformer)); + } + }; + } + } + + public static interface EntryTransformer { + public V2 transformEntry(@Nullable K var1, @Nullable V1 var2); + } + + private static class UnmodifiableBiMap + extends ForwardingMap + implements BiMap, + Serializable { + final Map unmodifiableMap; + final BiMap delegate; + BiMap inverse; + transient Set values; + private static final long serialVersionUID = 0L; + + UnmodifiableBiMap(BiMap delegate, @Nullable BiMap inverse) { + this.unmodifiableMap = Collections.unmodifiableMap(delegate); + this.delegate = delegate; + this.inverse = inverse; + } + + @Override + protected Map delegate() { + return this.unmodifiableMap; + } + + @Override + public V forcePut(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public BiMap inverse() { + BiMap result = this.inverse; + return result == null ? (this.inverse = new UnmodifiableBiMap(this.delegate.inverse(), this)) : result; + } + + @Override + public Set values() { + Set result = this.values; + return result == null ? (this.values = Collections.unmodifiableSet(this.delegate.values())) : result; + } + } + + private static final class BiMapConverter + extends Converter + implements Serializable { + private final BiMap bimap; + private static final long serialVersionUID = 0L; + + BiMapConverter(BiMap bimap) { + this.bimap = Preconditions.checkNotNull(bimap); + } + + @Override + protected B doForward(A a) { + return BiMapConverter.convert(this.bimap, a); + } + + @Override + protected A doBackward(B b) { + return BiMapConverter.convert(this.bimap.inverse(), b); + } + + private static Y convert(BiMap bimap, X input) { + Object output = bimap.get(input); + Preconditions.checkArgument(output != null, "No non-null mapping present for input: %s", input); + return (Y)output; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof BiMapConverter) { + BiMapConverter that = (BiMapConverter)object; + return this.bimap.equals(that.bimap); + } + return false; + } + + public int hashCode() { + return this.bimap.hashCode(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.bimap)); + return new StringBuilder(18 + string.length()).append("Maps.asConverter(").append(string).append(")").toString(); + } + } + + static class UnmodifiableEntrySet + extends UnmodifiableEntries + implements Set> { + UnmodifiableEntrySet(Set> entries) { + super(entries); + } + + @Override + public boolean equals(@Nullable Object object) { + return Sets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + static class UnmodifiableEntries + extends ForwardingCollection> { + private final Collection> entries; + + UnmodifiableEntries(Collection> entries) { + this.entries = entries; + } + + @Override + protected Collection> delegate() { + return this.entries; + } + + @Override + public Iterator> iterator() { + final Iterator delegate = super.iterator(); + return new UnmodifiableIterator>(){ + + @Override + public boolean hasNext() { + return delegate.hasNext(); + } + + @Override + public Map.Entry next() { + return Maps.unmodifiableEntry((Map.Entry)delegate.next()); + } + }; + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + } + + @GwtIncompatible(value="NavigableMap") + private static final class NavigableAsMapView + extends AbstractNavigableMap { + private final NavigableSet set; + private final Function function; + + NavigableAsMapView(NavigableSet ks, Function vFunction) { + this.set = Preconditions.checkNotNull(ks); + this.function = Preconditions.checkNotNull(vFunction); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + return Maps.asMap(this.set.subSet(fromKey, fromInclusive, toKey, toInclusive), this.function); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + return Maps.asMap(this.set.headSet(toKey, inclusive), this.function); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return Maps.asMap(this.set.tailSet(fromKey, inclusive), this.function); + } + + @Override + public Comparator comparator() { + return this.set.comparator(); + } + + @Override + @Nullable + public V get(@Nullable Object key) { + if (Collections2.safeContains(this.set, key)) { + Object k = key; + return this.function.apply(k); + } + return null; + } + + @Override + public void clear() { + this.set.clear(); + } + + @Override + Iterator> entryIterator() { + return Maps.asMapEntryIterator(this.set, this.function); + } + + @Override + Iterator> descendingEntryIterator() { + return this.descendingMap().entrySet().iterator(); + } + + @Override + public NavigableSet navigableKeySet() { + return Maps.removeOnlyNavigableSet(this.set); + } + + @Override + public int size() { + return this.set.size(); + } + + @Override + public NavigableMap descendingMap() { + return Maps.asMap(this.set.descendingSet(), this.function); + } + } + + private static class SortedAsMapView + extends AsMapView + implements SortedMap { + SortedAsMapView(SortedSet set, Function function) { + super(set, function); + } + + @Override + SortedSet backingSet() { + return (SortedSet)super.backingSet(); + } + + @Override + public Comparator comparator() { + return this.backingSet().comparator(); + } + + @Override + public Set keySet() { + return Maps.removeOnlySortedSet((SortedSet)this.backingSet()); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return Maps.asMap(this.backingSet().subSet(fromKey, toKey), this.function); + } + + @Override + public SortedMap headMap(K toKey) { + return Maps.asMap(this.backingSet().headSet(toKey), this.function); + } + + @Override + public SortedMap tailMap(K fromKey) { + return Maps.asMap(this.backingSet().tailSet(fromKey), this.function); + } + + @Override + public K firstKey() { + return (K)this.backingSet().first(); + } + + @Override + public K lastKey() { + return (K)this.backingSet().last(); + } + } + + private static class AsMapView + extends ImprovedAbstractMap { + private final Set set; + final Function function; + + Set backingSet() { + return this.set; + } + + AsMapView(Set set, Function function) { + this.set = Preconditions.checkNotNull(set); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public Set createKeySet() { + return Maps.removeOnlySet(this.backingSet()); + } + + @Override + Collection createValues() { + return Collections2.transform(this.set, this.function); + } + + @Override + public int size() { + return this.backingSet().size(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.backingSet().contains(key); + } + + @Override + public V get(@Nullable Object key) { + if (Collections2.safeContains(this.backingSet(), key)) { + Object k = key; + return this.function.apply(k); + } + return null; + } + + @Override + public V remove(@Nullable Object key) { + if (this.backingSet().remove(key)) { + Object k = key; + return this.function.apply(k); + } + return null; + } + + @Override + public void clear() { + this.backingSet().clear(); + } + + @Override + protected Set> createEntrySet() { + return new EntrySet(){ + + @Override + Map map() { + return AsMapView.this; + } + + @Override + public Iterator> iterator() { + return Maps.asMapEntryIterator(AsMapView.this.backingSet(), AsMapView.this.function); + } + }; + } + } + + static class SortedMapDifferenceImpl + extends MapDifferenceImpl + implements SortedMapDifference { + SortedMapDifferenceImpl(SortedMap onlyOnLeft, SortedMap onlyOnRight, SortedMap onBoth, SortedMap> differences) { + super(onlyOnLeft, onlyOnRight, onBoth, differences); + } + + @Override + public SortedMap> entriesDiffering() { + return (SortedMap)super.entriesDiffering(); + } + + @Override + public SortedMap entriesInCommon() { + return (SortedMap)super.entriesInCommon(); + } + + @Override + public SortedMap entriesOnlyOnLeft() { + return (SortedMap)super.entriesOnlyOnLeft(); + } + + @Override + public SortedMap entriesOnlyOnRight() { + return (SortedMap)super.entriesOnlyOnRight(); + } + } + + static class ValueDifferenceImpl + implements MapDifference.ValueDifference { + private final V left; + private final V right; + + static MapDifference.ValueDifference create(@Nullable V left, @Nullable V right) { + return new ValueDifferenceImpl(left, right); + } + + private ValueDifferenceImpl(@Nullable V left, @Nullable V right) { + this.left = left; + this.right = right; + } + + @Override + public V leftValue() { + return this.left; + } + + @Override + public V rightValue() { + return this.right; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof MapDifference.ValueDifference) { + MapDifference.ValueDifference that = (MapDifference.ValueDifference)object; + return Objects.equal(this.left, that.leftValue()) && Objects.equal(this.right, that.rightValue()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.left, this.right); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.left)); + String string2 = String.valueOf(String.valueOf(this.right)); + return new StringBuilder(4 + string.length() + string2.length()).append("(").append(string).append(", ").append(string2).append(")").toString(); + } + } + + static class MapDifferenceImpl + implements MapDifference { + final Map onlyOnLeft; + final Map onlyOnRight; + final Map onBoth; + final Map> differences; + + MapDifferenceImpl(Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) { + this.onlyOnLeft = Maps.unmodifiableMap(onlyOnLeft); + this.onlyOnRight = Maps.unmodifiableMap(onlyOnRight); + this.onBoth = Maps.unmodifiableMap(onBoth); + this.differences = Maps.unmodifiableMap(differences); + } + + @Override + public boolean areEqual() { + return this.onlyOnLeft.isEmpty() && this.onlyOnRight.isEmpty() && this.differences.isEmpty(); + } + + @Override + public Map entriesOnlyOnLeft() { + return this.onlyOnLeft; + } + + @Override + public Map entriesOnlyOnRight() { + return this.onlyOnRight; + } + + @Override + public Map entriesInCommon() { + return this.onBoth; + } + + @Override + public Map> entriesDiffering() { + return this.differences; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof MapDifference) { + MapDifference other = (MapDifference)object; + return this.entriesOnlyOnLeft().equals(other.entriesOnlyOnLeft()) && this.entriesOnlyOnRight().equals(other.entriesOnlyOnRight()) && this.entriesInCommon().equals(other.entriesInCommon()) && this.entriesDiffering().equals(other.entriesDiffering()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.entriesOnlyOnLeft(), this.entriesOnlyOnRight(), this.entriesInCommon(), this.entriesDiffering()); + } + + public String toString() { + if (this.areEqual()) { + return "equal"; + } + StringBuilder result = new StringBuilder("not equal"); + if (!this.onlyOnLeft.isEmpty()) { + result.append(": only on left=").append(this.onlyOnLeft); + } + if (!this.onlyOnRight.isEmpty()) { + result.append(": only on right=").append(this.onlyOnRight); + } + if (!this.differences.isEmpty()) { + result.append(": value differences=").append(this.differences); + } + return result.toString(); + } + } + + private static enum EntryFunction implements Function, Object> + { + KEY{ + + @Override + @Nullable + public Object apply(Map.Entry entry) { + return entry.getKey(); + } + } + , + VALUE{ + + @Override + @Nullable + public Object apply(Map.Entry entry) { + return entry.getValue(); + } + }; + + } +} diff --git a/src/com/google/common/collect/MinMaxPriorityQueue.java b/src/com/google/common/collect/MinMaxPriorityQueue.java new file mode 100644 index 0000000..955ffd4 --- /dev/null +++ b/src/com/google/common/collect/MinMaxPriorityQueue.java @@ -0,0 +1,570 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Ordering; +import com.google.common.math.IntMath; +import java.util.AbstractQueue; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; + +@Beta +public final class MinMaxPriorityQueue +extends AbstractQueue { + private final Heap minHeap; + private final Heap maxHeap; + @VisibleForTesting + final int maximumSize; + private Object[] queue; + private int size; + private int modCount; + private static final int EVEN_POWERS_OF_TWO = 0x55555555; + private static final int ODD_POWERS_OF_TWO = -1431655766; + private static final int DEFAULT_CAPACITY = 11; + + public static > MinMaxPriorityQueue create() { + return new Builder(Ordering.natural()).create(); + } + + public static > MinMaxPriorityQueue create(Iterable initialContents) { + return new Builder(Ordering.natural()).create(initialContents); + } + + public static Builder orderedBy(Comparator comparator) { + return new Builder(comparator); + } + + public static Builder expectedSize(int expectedSize) { + return new Builder(Ordering.natural()).expectedSize(expectedSize); + } + + public static Builder maximumSize(int maximumSize) { + return new Builder(Ordering.natural()).maximumSize(maximumSize); + } + + private MinMaxPriorityQueue(Builder builder, int queueSize) { + Ordering ordering = ((Builder)builder).ordering(); + this.minHeap = new Heap(ordering); + this.minHeap.otherHeap = this.maxHeap = new Heap(ordering.reverse()); + this.maxHeap.otherHeap = this.minHeap; + this.maximumSize = ((Builder)builder).maximumSize; + this.queue = new Object[queueSize]; + } + + @Override + public int size() { + return this.size; + } + + @Override + public boolean add(E element) { + this.offer(element); + return true; + } + + @Override + public boolean addAll(Collection newElements) { + boolean modified = false; + for (E element : newElements) { + this.offer(element); + modified = true; + } + return modified; + } + + @Override + public boolean offer(E element) { + Preconditions.checkNotNull(element); + ++this.modCount; + int insertIndex = this.size++; + this.growIfNeeded(); + this.heapForIndex(insertIndex).bubbleUp(insertIndex, element); + return this.size <= this.maximumSize || this.pollLast() != element; + } + + @Override + public E poll() { + return this.isEmpty() ? null : (E)this.removeAndGet(0); + } + + E elementData(int index) { + return (E)this.queue[index]; + } + + @Override + public E peek() { + return this.isEmpty() ? null : (E)this.elementData(0); + } + + private int getMaxElementIndex() { + switch (this.size) { + case 1: { + return 0; + } + case 2: { + return 1; + } + } + return this.maxHeap.compareElements(1, 2) <= 0 ? 1 : 2; + } + + public E pollFirst() { + return this.poll(); + } + + public E removeFirst() { + return this.remove(); + } + + public E peekFirst() { + return this.peek(); + } + + public E pollLast() { + return this.isEmpty() ? null : (E)this.removeAndGet(this.getMaxElementIndex()); + } + + public E removeLast() { + if (this.isEmpty()) { + throw new NoSuchElementException(); + } + return this.removeAndGet(this.getMaxElementIndex()); + } + + public E peekLast() { + return this.isEmpty() ? null : (E)this.elementData(this.getMaxElementIndex()); + } + + @VisibleForTesting + MoveDesc removeAt(int index) { + Preconditions.checkPositionIndex(index, this.size); + ++this.modCount; + --this.size; + if (this.size == index) { + this.queue[this.size] = null; + return null; + } + E actualLastElement = this.elementData(this.size); + int lastElementAt = this.heapForIndex(this.size).getCorrectLastElement(actualLastElement); + E toTrickle = this.elementData(this.size); + this.queue[this.size] = null; + MoveDesc changes = this.fillHole(index, toTrickle); + if (lastElementAt < index) { + if (changes == null) { + return new MoveDesc(actualLastElement, toTrickle); + } + return new MoveDesc(actualLastElement, changes.replaced); + } + return changes; + } + + private MoveDesc fillHole(int index, E toTrickle) { + int vacated; + Heap heap = this.heapForIndex(index); + int bubbledTo = heap.bubbleUpAlternatingLevels(vacated = heap.fillHoleAt(index), toTrickle); + if (bubbledTo == vacated) { + return heap.tryCrossOverAndBubbleUp(index, vacated, toTrickle); + } + return bubbledTo < index ? new MoveDesc(toTrickle, this.elementData(index)) : null; + } + + private E removeAndGet(int index) { + E value = this.elementData(index); + this.removeAt(index); + return value; + } + + private Heap heapForIndex(int i) { + return MinMaxPriorityQueue.isEvenLevel(i) ? this.minHeap : this.maxHeap; + } + + @VisibleForTesting + static boolean isEvenLevel(int index) { + int oneBased = index + 1; + Preconditions.checkState(oneBased > 0, "negative index"); + return (oneBased & 0x55555555) > (oneBased & 0xAAAAAAAA); + } + + @VisibleForTesting + boolean isIntact() { + for (int i = 1; i < this.size; ++i) { + if (this.heapForIndex(i).verifyIndex(i)) continue; + return false; + } + return true; + } + + @Override + public Iterator iterator() { + return new QueueIterator(); + } + + @Override + public void clear() { + for (int i = 0; i < this.size; ++i) { + this.queue[i] = null; + } + this.size = 0; + } + + @Override + public Object[] toArray() { + Object[] copyTo = new Object[this.size]; + System.arraycopy(this.queue, 0, copyTo, 0, this.size); + return copyTo; + } + + public Comparator comparator() { + return this.minHeap.ordering; + } + + @VisibleForTesting + int capacity() { + return this.queue.length; + } + + @VisibleForTesting + static int initialQueueSize(int configuredExpectedSize, int maximumSize, Iterable initialContents) { + int result; + int n = result = configuredExpectedSize == -1 ? 11 : configuredExpectedSize; + if (initialContents instanceof Collection) { + int initialSize = ((Collection)initialContents).size(); + result = Math.max(result, initialSize); + } + return MinMaxPriorityQueue.capAtMaximumSize(result, maximumSize); + } + + private void growIfNeeded() { + if (this.size > this.queue.length) { + int newCapacity = this.calculateNewCapacity(); + Object[] newQueue = new Object[newCapacity]; + System.arraycopy(this.queue, 0, newQueue, 0, this.queue.length); + this.queue = newQueue; + } + } + + private int calculateNewCapacity() { + int oldCapacity = this.queue.length; + int newCapacity = oldCapacity < 64 ? (oldCapacity + 1) * 2 : IntMath.checkedMultiply(oldCapacity / 2, 3); + return MinMaxPriorityQueue.capAtMaximumSize(newCapacity, this.maximumSize); + } + + private static int capAtMaximumSize(int queueSize, int maximumSize) { + return Math.min(queueSize - 1, maximumSize) + 1; + } + + private class QueueIterator + implements Iterator { + private int cursor = -1; + private int expectedModCount = MinMaxPriorityQueue.access$700(MinMaxPriorityQueue.this); + private Queue forgetMeNot; + private List skipMe; + private E lastFromForgetMeNot; + private boolean canRemove; + + private QueueIterator() { + } + + @Override + public boolean hasNext() { + this.checkModCount(); + return this.nextNotInSkipMe(this.cursor + 1) < MinMaxPriorityQueue.this.size() || this.forgetMeNot != null && !this.forgetMeNot.isEmpty(); + } + + @Override + public E next() { + this.checkModCount(); + int tempCursor = this.nextNotInSkipMe(this.cursor + 1); + if (tempCursor < MinMaxPriorityQueue.this.size()) { + this.cursor = tempCursor; + this.canRemove = true; + return MinMaxPriorityQueue.this.elementData(this.cursor); + } + if (this.forgetMeNot != null) { + this.cursor = MinMaxPriorityQueue.this.size(); + this.lastFromForgetMeNot = this.forgetMeNot.poll(); + if (this.lastFromForgetMeNot != null) { + this.canRemove = true; + return this.lastFromForgetMeNot; + } + } + throw new NoSuchElementException("iterator moved past last element in queue."); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.canRemove); + this.checkModCount(); + this.canRemove = false; + ++this.expectedModCount; + if (this.cursor < MinMaxPriorityQueue.this.size()) { + MoveDesc moved = MinMaxPriorityQueue.this.removeAt(this.cursor); + if (moved != null) { + if (this.forgetMeNot == null) { + this.forgetMeNot = new ArrayDeque(); + this.skipMe = new ArrayList(3); + } + this.forgetMeNot.add(moved.toTrickle); + this.skipMe.add(moved.replaced); + } + --this.cursor; + } else { + Preconditions.checkState(this.removeExact(this.lastFromForgetMeNot)); + this.lastFromForgetMeNot = null; + } + } + + private boolean containsExact(Iterable elements, E target) { + for (Object element : elements) { + if (element != target) continue; + return true; + } + return false; + } + + boolean removeExact(Object target) { + for (int i = 0; i < MinMaxPriorityQueue.this.size; ++i) { + if (MinMaxPriorityQueue.this.queue[i] != target) continue; + MinMaxPriorityQueue.this.removeAt(i); + return true; + } + return false; + } + + void checkModCount() { + if (MinMaxPriorityQueue.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + private int nextNotInSkipMe(int c) { + if (this.skipMe != null) { + while (c < MinMaxPriorityQueue.this.size() && this.containsExact(this.skipMe, MinMaxPriorityQueue.this.elementData(c))) { + ++c; + } + } + return c; + } + } + + private class Heap { + final Ordering ordering; + Heap otherHeap; + + Heap(Ordering ordering) { + this.ordering = ordering; + } + + int compareElements(int a, int b) { + return this.ordering.compare(MinMaxPriorityQueue.this.elementData(a), MinMaxPriorityQueue.this.elementData(b)); + } + + MoveDesc tryCrossOverAndBubbleUp(int removeIndex, int vacated, E toTrickle) { + int crossOver = this.crossOver(vacated, toTrickle); + if (crossOver == vacated) { + return null; + } + Object parent = crossOver < removeIndex ? MinMaxPriorityQueue.this.elementData(removeIndex) : MinMaxPriorityQueue.this.elementData(this.getParentIndex(removeIndex)); + if (this.otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle) < removeIndex) { + return new MoveDesc(toTrickle, parent); + } + return null; + } + + void bubbleUp(int index, E x) { + Heap heap; + int crossOver = this.crossOverUp(index, x); + if (crossOver == index) { + heap = this; + } else { + index = crossOver; + heap = this.otherHeap; + } + heap.bubbleUpAlternatingLevels(index, x); + } + + int bubbleUpAlternatingLevels(int index, E x) { + int grandParentIndex; + Object e; + while (index > 2 && this.ordering.compare(e = MinMaxPriorityQueue.this.elementData(grandParentIndex = this.getGrandparentIndex(index)), x) > 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = e; + index = grandParentIndex; + } + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = x; + return index; + } + + int findMin(int index, int len) { + if (index >= MinMaxPriorityQueue.this.size) { + return -1; + } + Preconditions.checkState(index > 0); + int limit = Math.min(index, MinMaxPriorityQueue.this.size - len) + len; + int minIndex = index; + for (int i = index + 1; i < limit; ++i) { + if (this.compareElements(i, minIndex) >= 0) continue; + minIndex = i; + } + return minIndex; + } + + int findMinChild(int index) { + return this.findMin(this.getLeftChildIndex(index), 2); + } + + int findMinGrandChild(int index) { + int leftChildIndex = this.getLeftChildIndex(index); + if (leftChildIndex < 0) { + return -1; + } + return this.findMin(this.getLeftChildIndex(leftChildIndex), 4); + } + + int crossOverUp(int index, E x) { + Object uncleElement; + int grandparentIndex; + int uncleIndex; + if (index == 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[0] = x; + return 0; + } + int parentIndex = this.getParentIndex(index); + Object parentElement = MinMaxPriorityQueue.this.elementData(parentIndex); + if (parentIndex != 0 && (uncleIndex = this.getRightChildIndex(grandparentIndex = this.getParentIndex(parentIndex))) != parentIndex && this.getLeftChildIndex(uncleIndex) >= MinMaxPriorityQueue.this.size && this.ordering.compare(uncleElement = MinMaxPriorityQueue.this.elementData(uncleIndex), parentElement) < 0) { + parentIndex = uncleIndex; + parentElement = uncleElement; + } + if (this.ordering.compare(parentElement, x) < 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = parentElement; + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[parentIndex] = x; + return parentIndex; + } + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = x; + return index; + } + + int getCorrectLastElement(E actualLastElement) { + Object uncleElement; + int grandparentIndex; + int uncleIndex; + int parentIndex = this.getParentIndex(MinMaxPriorityQueue.this.size); + if (parentIndex != 0 && (uncleIndex = this.getRightChildIndex(grandparentIndex = this.getParentIndex(parentIndex))) != parentIndex && this.getLeftChildIndex(uncleIndex) >= MinMaxPriorityQueue.this.size && this.ordering.compare(uncleElement = MinMaxPriorityQueue.this.elementData(uncleIndex), actualLastElement) < 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[uncleIndex] = actualLastElement; + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[((MinMaxPriorityQueue)MinMaxPriorityQueue.this).size] = uncleElement; + return uncleIndex; + } + return MinMaxPriorityQueue.this.size; + } + + int crossOver(int index, E x) { + int minChildIndex = this.findMinChild(index); + if (minChildIndex > 0 && this.ordering.compare(MinMaxPriorityQueue.this.elementData(minChildIndex), x) < 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = MinMaxPriorityQueue.this.elementData(minChildIndex); + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[minChildIndex] = x; + return minChildIndex; + } + return this.crossOverUp(index, x); + } + + int fillHoleAt(int index) { + int minGrandchildIndex; + while ((minGrandchildIndex = this.findMinGrandChild(index)) > 0) { + ((MinMaxPriorityQueue)MinMaxPriorityQueue.this).queue[index] = MinMaxPriorityQueue.this.elementData(minGrandchildIndex); + index = minGrandchildIndex; + } + return index; + } + + private boolean verifyIndex(int i) { + if (this.getLeftChildIndex(i) < MinMaxPriorityQueue.this.size && this.compareElements(i, this.getLeftChildIndex(i)) > 0) { + return false; + } + if (this.getRightChildIndex(i) < MinMaxPriorityQueue.this.size && this.compareElements(i, this.getRightChildIndex(i)) > 0) { + return false; + } + if (i > 0 && this.compareElements(i, this.getParentIndex(i)) > 0) { + return false; + } + return i <= 2 || this.compareElements(this.getGrandparentIndex(i), i) <= 0; + } + + private int getLeftChildIndex(int i) { + return i * 2 + 1; + } + + private int getRightChildIndex(int i) { + return i * 2 + 2; + } + + private int getParentIndex(int i) { + return (i - 1) / 2; + } + + private int getGrandparentIndex(int i) { + return this.getParentIndex(this.getParentIndex(i)); + } + } + + static class MoveDesc { + final E toTrickle; + final E replaced; + + MoveDesc(E toTrickle, E replaced) { + this.toTrickle = toTrickle; + this.replaced = replaced; + } + } + + @Beta + public static final class Builder { + private static final int UNSET_EXPECTED_SIZE = -1; + private final Comparator comparator; + private int expectedSize = -1; + private int maximumSize = Integer.MAX_VALUE; + + private Builder(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + public Builder expectedSize(int expectedSize) { + Preconditions.checkArgument(expectedSize >= 0); + this.expectedSize = expectedSize; + return this; + } + + public Builder maximumSize(int maximumSize) { + Preconditions.checkArgument(maximumSize > 0); + this.maximumSize = maximumSize; + return this; + } + + public MinMaxPriorityQueue create() { + return this.create(Collections.emptySet()); + } + + public MinMaxPriorityQueue create(Iterable initialContents) { + MinMaxPriorityQueue queue = new MinMaxPriorityQueue(this, MinMaxPriorityQueue.initialQueueSize(this.expectedSize, this.maximumSize, initialContents)); + for (T element : initialContents) { + queue.offer(element); + } + return queue; + } + + private Ordering ordering() { + return Ordering.from(this.comparator); + } + } +} diff --git a/src/com/google/common/collect/Multimap.java b/src/com/google/common/collect/Multimap.java new file mode 100644 index 0000000..88d50bf --- /dev/null +++ b/src/com/google/common/collect/Multimap.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Multiset; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public interface Multimap { + public int size(); + + public boolean isEmpty(); + + public boolean containsKey(@Nullable Object var1); + + public boolean containsValue(@Nullable Object var1); + + public boolean containsEntry(@Nullable Object var1, @Nullable Object var2); + + public boolean put(@Nullable K var1, @Nullable V var2); + + public boolean remove(@Nullable Object var1, @Nullable Object var2); + + public boolean putAll(@Nullable K var1, Iterable var2); + + public boolean putAll(Multimap var1); + + public Collection replaceValues(@Nullable K var1, Iterable var2); + + public Collection removeAll(@Nullable Object var1); + + public void clear(); + + public Collection get(@Nullable K var1); + + public Set keySet(); + + public Multiset keys(); + + public Collection values(); + + public Collection> entries(); + + public Map> asMap(); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); +} diff --git a/src/com/google/common/collect/MultimapBuilder.java b/src/com/google/common/collect/MultimapBuilder.java new file mode 100644 index 0000000..d65edc7 --- /dev/null +++ b/src/com/google/common/collect/MultimapBuilder.java @@ -0,0 +1,330 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Ordering; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.SortedSetMultimap; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +@Beta +@GwtCompatible +public abstract class MultimapBuilder { + private static final int DEFAULT_EXPECTED_KEYS = 8; + + private MultimapBuilder() { + } + + public static MultimapBuilderWithKeys hashKeys() { + return MultimapBuilder.hashKeys(8); + } + + public static MultimapBuilderWithKeys hashKeys(final int expectedKeys) { + CollectPreconditions.checkNonnegative(expectedKeys, "expectedKeys"); + return new MultimapBuilderWithKeys(){ + + @Override + Map> createMap() { + return new HashMap(expectedKeys); + } + }; + } + + public static MultimapBuilderWithKeys linkedHashKeys() { + return MultimapBuilder.linkedHashKeys(8); + } + + public static MultimapBuilderWithKeys linkedHashKeys(final int expectedKeys) { + CollectPreconditions.checkNonnegative(expectedKeys, "expectedKeys"); + return new MultimapBuilderWithKeys(){ + + @Override + Map> createMap() { + return new LinkedHashMap(expectedKeys); + } + }; + } + + public static MultimapBuilderWithKeys treeKeys() { + return MultimapBuilder.treeKeys(Ordering.natural()); + } + + public static MultimapBuilderWithKeys treeKeys(final Comparator comparator) { + Preconditions.checkNotNull(comparator); + return new MultimapBuilderWithKeys(){ + + @Override + Map> createMap() { + return new TreeMap(comparator); + } + }; + } + + public static > MultimapBuilderWithKeys enumKeys(final Class keyClass) { + Preconditions.checkNotNull(keyClass); + return new MultimapBuilderWithKeys(){ + + @Override + Map> createMap() { + return new EnumMap(keyClass); + } + }; + } + + public abstract Multimap build(); + + public Multimap build(Multimap multimap) { + Multimap result = this.build(); + result.putAll(multimap); + return result; + } + + public static abstract class SortedSetMultimapBuilder + extends SetMultimapBuilder { + SortedSetMultimapBuilder() { + } + + @Override + public abstract SortedSetMultimap build(); + + @Override + public SortedSetMultimap build(Multimap multimap) { + return (SortedSetMultimap)super.build((Multimap)multimap); + } + } + + public static abstract class SetMultimapBuilder + extends MultimapBuilder { + SetMultimapBuilder() { + } + + @Override + public abstract SetMultimap build(); + + @Override + public SetMultimap build(Multimap multimap) { + return (SetMultimap)super.build(multimap); + } + } + + public static abstract class ListMultimapBuilder + extends MultimapBuilder { + ListMultimapBuilder() { + } + + @Override + public abstract ListMultimap build(); + + @Override + public ListMultimap build(Multimap multimap) { + return (ListMultimap)super.build(multimap); + } + } + + public static abstract class MultimapBuilderWithKeys { + private static final int DEFAULT_EXPECTED_VALUES_PER_KEY = 2; + + MultimapBuilderWithKeys() { + } + + abstract Map> createMap(); + + public ListMultimapBuilder arrayListValues() { + return this.arrayListValues(2); + } + + public ListMultimapBuilder arrayListValues(final int expectedValuesPerKey) { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + return new ListMultimapBuilder(){ + + @Override + public ListMultimap build() { + return Multimaps.newListMultimap(MultimapBuilderWithKeys.this.createMap(), new ArrayListSupplier(expectedValuesPerKey)); + } + }; + } + + public ListMultimapBuilder linkedListValues() { + return new ListMultimapBuilder(){ + + @Override + public ListMultimap build() { + return Multimaps.newListMultimap(MultimapBuilderWithKeys.this.createMap(), LinkedListSupplier.instance()); + } + }; + } + + public SetMultimapBuilder hashSetValues() { + return this.hashSetValues(2); + } + + public SetMultimapBuilder hashSetValues(final int expectedValuesPerKey) { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + return new SetMultimapBuilder(){ + + @Override + public SetMultimap build() { + return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.createMap(), new HashSetSupplier(expectedValuesPerKey)); + } + }; + } + + public SetMultimapBuilder linkedHashSetValues() { + return this.linkedHashSetValues(2); + } + + public SetMultimapBuilder linkedHashSetValues(final int expectedValuesPerKey) { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + return new SetMultimapBuilder(){ + + @Override + public SetMultimap build() { + return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.createMap(), new LinkedHashSetSupplier(expectedValuesPerKey)); + } + }; + } + + public SortedSetMultimapBuilder treeSetValues() { + return this.treeSetValues(Ordering.natural()); + } + + public SortedSetMultimapBuilder treeSetValues(final Comparator comparator) { + Preconditions.checkNotNull(comparator, "comparator"); + return new SortedSetMultimapBuilder(){ + + @Override + public SortedSetMultimap build() { + return Multimaps.newSortedSetMultimap(MultimapBuilderWithKeys.this.createMap(), new TreeSetSupplier(comparator)); + } + }; + } + + public > SetMultimapBuilder enumSetValues(final Class valueClass) { + Preconditions.checkNotNull(valueClass, "valueClass"); + return new SetMultimapBuilder(){ + + @Override + public SetMultimap build() { + EnumSetSupplier factory = new EnumSetSupplier(valueClass); + return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.createMap(), factory); + } + }; + } + } + + private static final class EnumSetSupplier> + implements Supplier>, + Serializable { + private final Class clazz; + + EnumSetSupplier(Class clazz) { + this.clazz = Preconditions.checkNotNull(clazz); + } + + @Override + public Set get() { + return EnumSet.noneOf(this.clazz); + } + } + + private static final class TreeSetSupplier + implements Supplier>, + Serializable { + private final Comparator comparator; + + TreeSetSupplier(Comparator comparator) { + this.comparator = Preconditions.checkNotNull(comparator); + } + + @Override + public SortedSet get() { + return new TreeSet(this.comparator); + } + } + + private static final class LinkedHashSetSupplier + implements Supplier>, + Serializable { + private final int expectedValuesPerKey; + + LinkedHashSetSupplier(int expectedValuesPerKey) { + this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + } + + @Override + public Set get() { + return new LinkedHashSet(this.expectedValuesPerKey); + } + } + + private static final class HashSetSupplier + implements Supplier>, + Serializable { + private final int expectedValuesPerKey; + + HashSetSupplier(int expectedValuesPerKey) { + this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + } + + @Override + public Set get() { + return new HashSet(this.expectedValuesPerKey); + } + } + + private static enum LinkedListSupplier implements Supplier> + { + INSTANCE; + + + public static Supplier> instance() { + LinkedListSupplier result = INSTANCE; + return result; + } + + @Override + public List get() { + return new LinkedList(); + } + } + + private static final class ArrayListSupplier + implements Supplier>, + Serializable { + private final int expectedValuesPerKey; + + ArrayListSupplier(int expectedValuesPerKey) { + this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + } + + @Override + public List get() { + return new ArrayList(this.expectedValuesPerKey); + } + } +} diff --git a/src/com/google/common/collect/Multimaps.java b/src/com/google/common/collect/Multimaps.java new file mode 100644 index 0000000..45b4b1d --- /dev/null +++ b/src/com/google/common/collect/Multimaps.java @@ -0,0 +1,1190 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.AbstractListMultimap; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.AbstractMultimap; +import com.google.common.collect.AbstractMultiset; +import com.google.common.collect.AbstractSetMultimap; +import com.google.common.collect.AbstractSortedSetMultimap; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.FilteredEntryMultimap; +import com.google.common.collect.FilteredEntrySetMultimap; +import com.google.common.collect.FilteredKeyListMultimap; +import com.google.common.collect.FilteredKeyMultimap; +import com.google.common.collect.FilteredKeySetMultimap; +import com.google.common.collect.FilteredMultimap; +import com.google.common.collect.FilteredSetMultimap; +import com.google.common.collect.ForwardingMultimap; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Iterators; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedSetMultimap; +import com.google.common.collect.Synchronized; +import com.google.common.collect.TransformedIterator; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Multimaps { + private Multimaps() { + } + + public static Multimap newMultimap(Map> map, Supplier> factory) { + return new CustomMultimap(map, factory); + } + + public static ListMultimap newListMultimap(Map> map, Supplier> factory) { + return new CustomListMultimap(map, factory); + } + + public static SetMultimap newSetMultimap(Map> map, Supplier> factory) { + return new CustomSetMultimap(map, factory); + } + + public static SortedSetMultimap newSortedSetMultimap(Map> map, Supplier> factory) { + return new CustomSortedSetMultimap(map, factory); + } + + public static > M invertFrom(Multimap source, M dest) { + Preconditions.checkNotNull(dest); + for (Map.Entry entry : source.entries()) { + dest.put(entry.getValue(), entry.getKey()); + } + return dest; + } + + public static Multimap synchronizedMultimap(Multimap multimap) { + return Synchronized.multimap(multimap, null); + } + + public static Multimap unmodifiableMultimap(Multimap delegate) { + if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) { + return delegate; + } + return new UnmodifiableMultimap(delegate); + } + + @Deprecated + public static Multimap unmodifiableMultimap(ImmutableMultimap delegate) { + return Preconditions.checkNotNull(delegate); + } + + public static SetMultimap synchronizedSetMultimap(SetMultimap multimap) { + return Synchronized.setMultimap(multimap, null); + } + + public static SetMultimap unmodifiableSetMultimap(SetMultimap delegate) { + if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) { + return delegate; + } + return new UnmodifiableSetMultimap(delegate); + } + + @Deprecated + public static SetMultimap unmodifiableSetMultimap(ImmutableSetMultimap delegate) { + return Preconditions.checkNotNull(delegate); + } + + public static SortedSetMultimap synchronizedSortedSetMultimap(SortedSetMultimap multimap) { + return Synchronized.sortedSetMultimap(multimap, null); + } + + public static SortedSetMultimap unmodifiableSortedSetMultimap(SortedSetMultimap delegate) { + if (delegate instanceof UnmodifiableSortedSetMultimap) { + return delegate; + } + return new UnmodifiableSortedSetMultimap(delegate); + } + + public static ListMultimap synchronizedListMultimap(ListMultimap multimap) { + return Synchronized.listMultimap(multimap, null); + } + + public static ListMultimap unmodifiableListMultimap(ListMultimap delegate) { + if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) { + return delegate; + } + return new UnmodifiableListMultimap(delegate); + } + + @Deprecated + public static ListMultimap unmodifiableListMultimap(ImmutableListMultimap delegate) { + return Preconditions.checkNotNull(delegate); + } + + private static Collection unmodifiableValueCollection(Collection collection) { + if (collection instanceof SortedSet) { + return Collections.unmodifiableSortedSet((SortedSet)collection); + } + if (collection instanceof Set) { + return Collections.unmodifiableSet((Set)collection); + } + if (collection instanceof List) { + return Collections.unmodifiableList((List)collection); + } + return Collections.unmodifiableCollection(collection); + } + + private static Collection> unmodifiableEntries(Collection> entries) { + if (entries instanceof Set) { + return Maps.unmodifiableEntrySet((Set)entries); + } + return new Maps.UnmodifiableEntries(Collections.unmodifiableCollection(entries)); + } + + @Beta + public static Map> asMap(ListMultimap multimap) { + return multimap.asMap(); + } + + @Beta + public static Map> asMap(SetMultimap multimap) { + return multimap.asMap(); + } + + @Beta + public static Map> asMap(SortedSetMultimap multimap) { + return multimap.asMap(); + } + + @Beta + public static Map> asMap(Multimap multimap) { + return multimap.asMap(); + } + + public static SetMultimap forMap(Map map) { + return new MapMultimap(map); + } + + public static Multimap transformValues(Multimap fromMultimap, Function function) { + Preconditions.checkNotNull(function); + Maps.EntryTransformer transformer = Maps.asEntryTransformer(function); + return Multimaps.transformEntries(fromMultimap, transformer); + } + + public static Multimap transformEntries(Multimap fromMap, Maps.EntryTransformer transformer) { + return new TransformedEntriesMultimap(fromMap, transformer); + } + + public static ListMultimap transformValues(ListMultimap fromMultimap, Function function) { + Preconditions.checkNotNull(function); + Maps.EntryTransformer transformer = Maps.asEntryTransformer(function); + return Multimaps.transformEntries(fromMultimap, transformer); + } + + public static ListMultimap transformEntries(ListMultimap fromMap, Maps.EntryTransformer transformer) { + return new TransformedEntriesListMultimap(fromMap, transformer); + } + + public static ImmutableListMultimap index(Iterable values, Function keyFunction) { + return Multimaps.index(values.iterator(), keyFunction); + } + + public static ImmutableListMultimap index(Iterator values, Function keyFunction) { + Preconditions.checkNotNull(keyFunction); + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + while (values.hasNext()) { + V value = values.next(); + Preconditions.checkNotNull(value, values); + builder.put((Object)keyFunction.apply(value), (Object)value); + } + return builder.build(); + } + + public static Multimap filterKeys(Multimap unfiltered, Predicate keyPredicate) { + if (unfiltered instanceof SetMultimap) { + return Multimaps.filterKeys((SetMultimap)unfiltered, keyPredicate); + } + if (unfiltered instanceof ListMultimap) { + return Multimaps.filterKeys((ListMultimap)unfiltered, keyPredicate); + } + if (unfiltered instanceof FilteredKeyMultimap) { + FilteredKeyMultimap prev = (FilteredKeyMultimap)unfiltered; + return new FilteredKeyMultimap(prev.unfiltered, Predicates.and(prev.keyPredicate, keyPredicate)); + } + if (unfiltered instanceof FilteredMultimap) { + FilteredMultimap prev = (FilteredMultimap)unfiltered; + return Multimaps.filterFiltered(prev, Maps.keyPredicateOnEntries(keyPredicate)); + } + return new FilteredKeyMultimap(unfiltered, keyPredicate); + } + + public static SetMultimap filterKeys(SetMultimap unfiltered, Predicate keyPredicate) { + if (unfiltered instanceof FilteredKeySetMultimap) { + FilteredKeySetMultimap prev = (FilteredKeySetMultimap)unfiltered; + return new FilteredKeySetMultimap(prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate)); + } + if (unfiltered instanceof FilteredSetMultimap) { + FilteredSetMultimap prev = (FilteredSetMultimap)unfiltered; + return Multimaps.filterFiltered(prev, Maps.keyPredicateOnEntries(keyPredicate)); + } + return new FilteredKeySetMultimap(unfiltered, keyPredicate); + } + + public static ListMultimap filterKeys(ListMultimap unfiltered, Predicate keyPredicate) { + if (unfiltered instanceof FilteredKeyListMultimap) { + FilteredKeyListMultimap prev = (FilteredKeyListMultimap)unfiltered; + return new FilteredKeyListMultimap(prev.unfiltered(), Predicates.and(prev.keyPredicate, keyPredicate)); + } + return new FilteredKeyListMultimap(unfiltered, keyPredicate); + } + + public static Multimap filterValues(Multimap unfiltered, Predicate valuePredicate) { + return Multimaps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + public static SetMultimap filterValues(SetMultimap unfiltered, Predicate valuePredicate) { + return Multimaps.filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + public static Multimap filterEntries(Multimap unfiltered, Predicate> entryPredicate) { + Preconditions.checkNotNull(entryPredicate); + if (unfiltered instanceof SetMultimap) { + return Multimaps.filterEntries((SetMultimap)unfiltered, entryPredicate); + } + return unfiltered instanceof FilteredMultimap ? Multimaps.filterFiltered((FilteredMultimap)unfiltered, entryPredicate) : new FilteredEntryMultimap(Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + public static SetMultimap filterEntries(SetMultimap unfiltered, Predicate> entryPredicate) { + Preconditions.checkNotNull(entryPredicate); + return unfiltered instanceof FilteredSetMultimap ? Multimaps.filterFiltered((FilteredSetMultimap)unfiltered, entryPredicate) : new FilteredEntrySetMultimap(Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + private static Multimap filterFiltered(FilteredMultimap multimap, Predicate> entryPredicate) { + Predicate> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate); + return new FilteredEntryMultimap(multimap.unfiltered(), predicate); + } + + private static SetMultimap filterFiltered(FilteredSetMultimap multimap, Predicate> entryPredicate) { + Predicate> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate); + return new FilteredEntrySetMultimap(multimap.unfiltered(), predicate); + } + + static boolean equalsImpl(Multimap multimap, @Nullable Object object) { + if (object == multimap) { + return true; + } + if (object instanceof Multimap) { + Multimap that = (Multimap)object; + return multimap.asMap().equals(that.asMap()); + } + return false; + } + + static final class AsMap + extends Maps.ImprovedAbstractMap> { + private final Multimap multimap; + + AsMap(Multimap multimap) { + this.multimap = Preconditions.checkNotNull(multimap); + } + + @Override + public int size() { + return this.multimap.keySet().size(); + } + + @Override + protected Set>> createEntrySet() { + return new EntrySet(); + } + + void removeValuesForKey(Object key) { + this.multimap.keySet().remove(key); + } + + @Override + public Collection get(Object key) { + return this.containsKey(key) ? this.multimap.get(key) : null; + } + + @Override + public Collection remove(Object key) { + return this.containsKey(key) ? this.multimap.removeAll(key) : null; + } + + @Override + public Set keySet() { + return this.multimap.keySet(); + } + + @Override + public boolean isEmpty() { + return this.multimap.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return this.multimap.containsKey(key); + } + + @Override + public void clear() { + this.multimap.clear(); + } + + class EntrySet + extends Maps.EntrySet> { + EntrySet() { + } + + @Override + Map> map() { + return AsMap.this; + } + + @Override + public Iterator>> iterator() { + return Maps.asMapEntryIterator(AsMap.this.multimap.keySet(), new Function>(){ + + @Override + public Collection apply(K key) { + return AsMap.this.multimap.get(key); + } + }); + } + + @Override + public boolean remove(Object o) { + if (!this.contains(o)) { + return false; + } + Map.Entry entry = (Map.Entry)o; + AsMap.this.removeValuesForKey(entry.getKey()); + return true; + } + } + } + + static abstract class Entries + extends AbstractCollection> { + Entries() { + } + + abstract Multimap multimap(); + + @Override + public int size() { + return this.multimap().size(); + } + + @Override + public boolean contains(@Nullable Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)o; + return this.multimap().containsEntry(entry.getKey(), entry.getValue()); + } + return false; + } + + @Override + public boolean remove(@Nullable Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)o; + return this.multimap().remove(entry.getKey(), entry.getValue()); + } + return false; + } + + @Override + public void clear() { + this.multimap().clear(); + } + } + + static class Keys + extends AbstractMultiset { + final Multimap multimap; + + Keys(Multimap multimap) { + this.multimap = multimap; + } + + @Override + Iterator> entryIterator() { + return new TransformedIterator>, Multiset.Entry>(this.multimap.asMap().entrySet().iterator()){ + + @Override + Multiset.Entry transform(final Map.Entry> backingEntry) { + return new Multisets.AbstractEntry(){ + + @Override + public K getElement() { + return backingEntry.getKey(); + } + + @Override + public int getCount() { + return ((Collection)backingEntry.getValue()).size(); + } + }; + } + }; + } + + @Override + int distinctElements() { + return this.multimap.asMap().size(); + } + + @Override + Set> createEntrySet() { + return new KeysEntrySet(); + } + + @Override + public boolean contains(@Nullable Object element) { + return this.multimap.containsKey(element); + } + + @Override + public Iterator iterator() { + return Maps.keyIterator(this.multimap.entries().iterator()); + } + + @Override + public int count(@Nullable Object element) { + Collection values = Maps.safeGet(this.multimap.asMap(), element); + return values == null ? 0 : values.size(); + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return this.count(element); + } + Collection values = Maps.safeGet(this.multimap.asMap(), element); + if (values == null) { + return 0; + } + int oldCount = values.size(); + if (occurrences >= oldCount) { + values.clear(); + } else { + Iterator iterator = values.iterator(); + for (int i = 0; i < occurrences; ++i) { + iterator.next(); + iterator.remove(); + } + } + return oldCount; + } + + @Override + public void clear() { + this.multimap.clear(); + } + + @Override + public Set elementSet() { + return this.multimap.keySet(); + } + + class KeysEntrySet + extends Multisets.EntrySet { + KeysEntrySet() { + } + + @Override + Multiset multiset() { + return Keys.this; + } + + @Override + public Iterator> iterator() { + return Keys.this.entryIterator(); + } + + @Override + public int size() { + return Keys.this.distinctElements(); + } + + @Override + public boolean isEmpty() { + return Keys.this.multimap.isEmpty(); + } + + @Override + public boolean contains(@Nullable Object o) { + if (o instanceof Multiset.Entry) { + Multiset.Entry entry = (Multiset.Entry)o; + Collection collection = Keys.this.multimap.asMap().get(entry.getElement()); + return collection != null && collection.size() == entry.getCount(); + } + return false; + } + + @Override + public boolean remove(@Nullable Object o) { + if (o instanceof Multiset.Entry) { + Multiset.Entry entry = (Multiset.Entry)o; + Collection collection = Keys.this.multimap.asMap().get(entry.getElement()); + if (collection != null && collection.size() == entry.getCount()) { + collection.clear(); + return true; + } + } + return false; + } + } + } + + private static final class TransformedEntriesListMultimap + extends TransformedEntriesMultimap + implements ListMultimap { + TransformedEntriesListMultimap(ListMultimap fromMultimap, Maps.EntryTransformer transformer) { + super(fromMultimap, transformer); + } + + @Override + List transform(K key, Collection values) { + return Lists.transform((List)values, Maps.asValueToValueFunction(this.transformer, key)); + } + + @Override + public List get(K key) { + return this.transform((Object)key, this.fromMultimap.get(key)); + } + + @Override + public List removeAll(Object key) { + return this.transform(key, this.fromMultimap.removeAll(key)); + } + + @Override + public List replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + } + + private static class TransformedEntriesMultimap + extends AbstractMultimap { + final Multimap fromMultimap; + final Maps.EntryTransformer transformer; + + TransformedEntriesMultimap(Multimap fromMultimap, Maps.EntryTransformer transformer) { + this.fromMultimap = Preconditions.checkNotNull(fromMultimap); + this.transformer = Preconditions.checkNotNull(transformer); + } + + Collection transform(K key, Collection values) { + Function function = Maps.asValueToValueFunction(this.transformer, key); + if (values instanceof List) { + return Lists.transform((List)values, function); + } + return Collections2.transform(values, function); + } + + @Override + Map> createAsMap() { + return Maps.transformEntries(this.fromMultimap.asMap(), new Maps.EntryTransformer, Collection>(){ + + @Override + public Collection transformEntry(K key, Collection value) { + return TransformedEntriesMultimap.this.transform(key, value); + } + }); + } + + @Override + public void clear() { + this.fromMultimap.clear(); + } + + @Override + public boolean containsKey(Object key) { + return this.fromMultimap.containsKey(key); + } + + @Override + Iterator> entryIterator() { + return Iterators.transform(this.fromMultimap.entries().iterator(), Maps.asEntryToEntryFunction(this.transformer)); + } + + @Override + public Collection get(K key) { + return this.transform(key, this.fromMultimap.get(key)); + } + + @Override + public boolean isEmpty() { + return this.fromMultimap.isEmpty(); + } + + @Override + public Set keySet() { + return this.fromMultimap.keySet(); + } + + @Override + public Multiset keys() { + return this.fromMultimap.keys(); + } + + @Override + public boolean put(K key, V2 value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(Multimap multimap) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + return this.get(key).remove(value); + } + + @Override + public Collection removeAll(Object key) { + return this.transform(key, this.fromMultimap.removeAll(key)); + } + + @Override + public Collection replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return this.fromMultimap.size(); + } + + @Override + Collection createValues() { + return Collections2.transform(this.fromMultimap.entries(), Maps.asEntryToValueFunction(this.transformer)); + } + } + + private static class MapMultimap + extends AbstractMultimap + implements SetMultimap, + Serializable { + final Map map; + private static final long serialVersionUID = 7845222491160860175L; + + MapMultimap(Map map) { + this.map = Preconditions.checkNotNull(map); + } + + @Override + public int size() { + return this.map.size(); + } + + @Override + public boolean containsKey(Object key) { + return this.map.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return this.map.containsValue(value); + } + + @Override + public boolean containsEntry(Object key, Object value) { + return this.map.entrySet().contains(Maps.immutableEntry(key, value)); + } + + @Override + public Set get(final K key) { + return new Sets.ImprovedAbstractSet(){ + + @Override + public Iterator iterator() { + return new Iterator(){ + int i; + + @Override + public boolean hasNext() { + return this.i == 0 && MapMultimap.this.map.containsKey(key); + } + + @Override + public V next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + ++this.i; + return MapMultimap.this.map.get(key); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.i == 1); + this.i = -1; + MapMultimap.this.map.remove(key); + } + }; + } + + @Override + public int size() { + return MapMultimap.this.map.containsKey(key) ? 1 : 0; + } + }; + } + + @Override + public boolean put(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(Multimap multimap) { + throw new UnsupportedOperationException(); + } + + @Override + public Set replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + return this.map.entrySet().remove(Maps.immutableEntry(key, value)); + } + + @Override + public Set removeAll(Object key) { + HashSet values = new HashSet(2); + if (!this.map.containsKey(key)) { + return values; + } + values.add(this.map.remove(key)); + return values; + } + + @Override + public void clear() { + this.map.clear(); + } + + @Override + public Set keySet() { + return this.map.keySet(); + } + + @Override + public Collection values() { + return this.map.values(); + } + + @Override + public Set> entries() { + return this.map.entrySet(); + } + + @Override + Iterator> entryIterator() { + return this.map.entrySet().iterator(); + } + + @Override + Map> createAsMap() { + return new AsMap(this); + } + + @Override + public int hashCode() { + return this.map.hashCode(); + } + } + + private static class UnmodifiableSortedSetMultimap + extends UnmodifiableSetMultimap + implements SortedSetMultimap { + private static final long serialVersionUID = 0L; + + UnmodifiableSortedSetMultimap(SortedSetMultimap delegate) { + super(delegate); + } + + @Override + public SortedSetMultimap delegate() { + return (SortedSetMultimap)super.delegate(); + } + + @Override + public SortedSet get(K key) { + return Collections.unmodifiableSortedSet(this.delegate().get(key)); + } + + @Override + public SortedSet removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public Comparator valueComparator() { + return this.delegate().valueComparator(); + } + } + + private static class UnmodifiableSetMultimap + extends UnmodifiableMultimap + implements SetMultimap { + private static final long serialVersionUID = 0L; + + UnmodifiableSetMultimap(SetMultimap delegate) { + super(delegate); + } + + @Override + public SetMultimap delegate() { + return (SetMultimap)super.delegate(); + } + + @Override + public Set get(K key) { + return Collections.unmodifiableSet(this.delegate().get(key)); + } + + @Override + public Set> entries() { + return Maps.unmodifiableEntrySet(this.delegate().entries()); + } + + @Override + public Set removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public Set replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + } + + private static class UnmodifiableListMultimap + extends UnmodifiableMultimap + implements ListMultimap { + private static final long serialVersionUID = 0L; + + UnmodifiableListMultimap(ListMultimap delegate) { + super(delegate); + } + + @Override + public ListMultimap delegate() { + return (ListMultimap)super.delegate(); + } + + @Override + public List get(K key) { + return Collections.unmodifiableList(this.delegate().get(key)); + } + + @Override + public List removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public List replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + } + + private static class UnmodifiableMultimap + extends ForwardingMultimap + implements Serializable { + final Multimap delegate; + transient Collection> entries; + transient Multiset keys; + transient Set keySet; + transient Collection values; + transient Map> map; + private static final long serialVersionUID = 0L; + + UnmodifiableMultimap(Multimap delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected Multimap delegate() { + return this.delegate; + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public Map> asMap() { + Map> result = this.map; + if (result == null) { + result = this.map = Collections.unmodifiableMap(Maps.transformValues(this.delegate.asMap(), new Function, Collection>(){ + + @Override + public Collection apply(Collection collection) { + return Multimaps.unmodifiableValueCollection(collection); + } + })); + } + return result; + } + + @Override + public Collection> entries() { + Collection result = this.entries; + if (result == null) { + this.entries = result = Multimaps.unmodifiableEntries(this.delegate.entries()); + } + return result; + } + + @Override + public Collection get(K key) { + return Multimaps.unmodifiableValueCollection(this.delegate.get(key)); + } + + @Override + public Multiset keys() { + Multiset result = this.keys; + if (result == null) { + this.keys = result = Multisets.unmodifiableMultiset(this.delegate.keys()); + } + return result; + } + + @Override + public Set keySet() { + Set result = this.keySet; + if (result == null) { + this.keySet = result = Collections.unmodifiableSet(this.delegate.keySet()); + } + return result; + } + + @Override + public boolean put(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean putAll(Multimap multimap) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection values() { + Collection result = this.values; + if (result == null) { + this.values = result = Collections.unmodifiableCollection(this.delegate.values()); + } + return result; + } + } + + private static class CustomSortedSetMultimap + extends AbstractSortedSetMultimap { + transient Supplier> factory; + transient Comparator valueComparator; + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 0L; + + CustomSortedSetMultimap(Map> map, Supplier> factory) { + super(map); + this.factory = Preconditions.checkNotNull(factory); + this.valueComparator = factory.get().comparator(); + } + + @Override + protected SortedSet createCollection() { + return this.factory.get(); + } + + @Override + public Comparator valueComparator() { + return this.valueComparator; + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.factory); + stream.writeObject(this.backingMap()); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.factory = (Supplier)stream.readObject(); + this.valueComparator = this.factory.get().comparator(); + Map map = (Map)stream.readObject(); + this.setMap(map); + } + } + + private static class CustomSetMultimap + extends AbstractSetMultimap { + transient Supplier> factory; + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 0L; + + CustomSetMultimap(Map> map, Supplier> factory) { + super(map); + this.factory = Preconditions.checkNotNull(factory); + } + + @Override + protected Set createCollection() { + return this.factory.get(); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.factory); + stream.writeObject(this.backingMap()); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.factory = (Supplier)stream.readObject(); + Map map = (Map)stream.readObject(); + this.setMap(map); + } + } + + private static class CustomListMultimap + extends AbstractListMultimap { + transient Supplier> factory; + @GwtIncompatible(value="java serialization not supported") + private static final long serialVersionUID = 0L; + + CustomListMultimap(Map> map, Supplier> factory) { + super(map); + this.factory = Preconditions.checkNotNull(factory); + } + + @Override + protected List createCollection() { + return this.factory.get(); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.factory); + stream.writeObject(this.backingMap()); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.factory = (Supplier)stream.readObject(); + Map map = (Map)stream.readObject(); + this.setMap(map); + } + } + + private static class CustomMultimap + extends AbstractMapBasedMultimap { + transient Supplier> factory; + @GwtIncompatible(value="java serialization not supported") + private static final long serialVersionUID = 0L; + + CustomMultimap(Map> map, Supplier> factory) { + super(map); + this.factory = Preconditions.checkNotNull(factory); + } + + @Override + protected Collection createCollection() { + return this.factory.get(); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.factory); + stream.writeObject(this.backingMap()); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.factory = (Supplier)stream.readObject(); + Map map = (Map)stream.readObject(); + this.setMap(map); + } + } +} diff --git a/src/com/google/common/collect/Multiset.java b/src/com/google/common/collect/Multiset.java new file mode 100644 index 0000000..89cb56c --- /dev/null +++ b/src/com/google/common/collect/Multiset.java @@ -0,0 +1,69 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public interface Multiset +extends Collection { + public int count(@Nullable Object var1); + + public int add(@Nullable E var1, int var2); + + public int remove(@Nullable Object var1, int var2); + + public int setCount(E var1, int var2); + + public boolean setCount(E var1, int var2, int var3); + + public Set elementSet(); + + public Set> entrySet(); + + @Override + public boolean equals(@Nullable Object var1); + + @Override + public int hashCode(); + + public String toString(); + + @Override + public Iterator iterator(); + + @Override + public boolean contains(@Nullable Object var1); + + @Override + public boolean containsAll(Collection var1); + + @Override + public boolean add(E var1); + + @Override + public boolean remove(@Nullable Object var1); + + @Override + public boolean removeAll(Collection var1); + + @Override + public boolean retainAll(Collection var1); + + public static interface Entry { + public E getElement(); + + public int getCount(); + + public boolean equals(Object var1); + + public int hashCode(); + + public String toString(); + } +} diff --git a/src/com/google/common/collect/Multisets.java b/src/com/google/common/collect/Multisets.java new file mode 100644 index 0000000..929a18d --- /dev/null +++ b/src/com/google/common/collect/Multisets.java @@ -0,0 +1,810 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractMultiset; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ForwardingMultiset; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedMultiset; +import com.google.common.collect.TransformedIterator; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.collect.UnmodifiableSortedMultiset; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Multisets { + private static final Ordering> DECREASING_COUNT_ORDERING = new Ordering>(){ + + @Override + public int compare(Multiset.Entry entry1, Multiset.Entry entry2) { + return Ints.compare(entry2.getCount(), entry1.getCount()); + } + }; + + private Multisets() { + } + + public static Multiset unmodifiableMultiset(Multiset multiset) { + if (multiset instanceof UnmodifiableMultiset || multiset instanceof ImmutableMultiset) { + Multiset result = multiset; + return result; + } + return new UnmodifiableMultiset(Preconditions.checkNotNull(multiset)); + } + + @Deprecated + public static Multiset unmodifiableMultiset(ImmutableMultiset multiset) { + return Preconditions.checkNotNull(multiset); + } + + @Beta + public static SortedMultiset unmodifiableSortedMultiset(SortedMultiset sortedMultiset) { + return new UnmodifiableSortedMultiset(Preconditions.checkNotNull(sortedMultiset)); + } + + public static Multiset.Entry immutableEntry(@Nullable E e, int n) { + return new ImmutableEntry(e, n); + } + + @Beta + public static Multiset filter(Multiset unfiltered, Predicate predicate) { + if (unfiltered instanceof FilteredMultiset) { + FilteredMultiset filtered = (FilteredMultiset)unfiltered; + Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate); + return new FilteredMultiset(filtered.unfiltered, combinedPredicate); + } + return new FilteredMultiset(unfiltered, predicate); + } + + static int inferDistinctElements(Iterable elements) { + if (elements instanceof Multiset) { + return ((Multiset)elements).elementSet().size(); + } + return 11; + } + + @Beta + public static Multiset union(final Multiset multiset1, final Multiset multiset2) { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + return new AbstractMultiset(){ + + @Override + public boolean contains(@Nullable Object element) { + return multiset1.contains(element) || multiset2.contains(element); + } + + @Override + public boolean isEmpty() { + return multiset1.isEmpty() && multiset2.isEmpty(); + } + + @Override + public int count(Object element) { + return Math.max(multiset1.count(element), multiset2.count(element)); + } + + @Override + Set createElementSet() { + return Sets.union(multiset1.elementSet(), multiset2.elementSet()); + } + + @Override + Iterator> entryIterator() { + final Iterator iterator1 = multiset1.entrySet().iterator(); + final Iterator iterator2 = multiset2.entrySet().iterator(); + return new AbstractIterator>(){ + + @Override + protected Multiset.Entry computeNext() { + if (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + Object element = entry1.getElement(); + int count = Math.max(entry1.getCount(), multiset2.count(element)); + return Multisets.immutableEntry(element, count); + } + while (iterator2.hasNext()) { + Multiset.Entry entry2 = (Multiset.Entry)iterator2.next(); + Object element = entry2.getElement(); + if (multiset1.contains(element)) continue; + return Multisets.immutableEntry(element, entry2.getCount()); + } + return (Multiset.Entry)this.endOfData(); + } + }; + } + + @Override + int distinctElements() { + return this.elementSet().size(); + } + }; + } + + public static Multiset intersection(final Multiset multiset1, final Multiset multiset2) { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + return new AbstractMultiset(){ + + @Override + public int count(Object element) { + int count1 = multiset1.count(element); + return count1 == 0 ? 0 : Math.min(count1, multiset2.count(element)); + } + + @Override + Set createElementSet() { + return Sets.intersection(multiset1.elementSet(), multiset2.elementSet()); + } + + @Override + Iterator> entryIterator() { + final Iterator iterator1 = multiset1.entrySet().iterator(); + return new AbstractIterator>(){ + + @Override + protected Multiset.Entry computeNext() { + while (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + Object element = entry1.getElement(); + int count = Math.min(entry1.getCount(), multiset2.count(element)); + if (count <= 0) continue; + return Multisets.immutableEntry(element, count); + } + return (Multiset.Entry)this.endOfData(); + } + }; + } + + @Override + int distinctElements() { + return this.elementSet().size(); + } + }; + } + + @Beta + public static Multiset sum(final Multiset multiset1, final Multiset multiset2) { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + return new AbstractMultiset(){ + + @Override + public boolean contains(@Nullable Object element) { + return multiset1.contains(element) || multiset2.contains(element); + } + + @Override + public boolean isEmpty() { + return multiset1.isEmpty() && multiset2.isEmpty(); + } + + @Override + public int size() { + return multiset1.size() + multiset2.size(); + } + + @Override + public int count(Object element) { + return multiset1.count(element) + multiset2.count(element); + } + + @Override + Set createElementSet() { + return Sets.union(multiset1.elementSet(), multiset2.elementSet()); + } + + @Override + Iterator> entryIterator() { + final Iterator iterator1 = multiset1.entrySet().iterator(); + final Iterator iterator2 = multiset2.entrySet().iterator(); + return new AbstractIterator>(){ + + @Override + protected Multiset.Entry computeNext() { + if (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + Object element = entry1.getElement(); + int count = entry1.getCount() + multiset2.count(element); + return Multisets.immutableEntry(element, count); + } + while (iterator2.hasNext()) { + Multiset.Entry entry2 = (Multiset.Entry)iterator2.next(); + Object element = entry2.getElement(); + if (multiset1.contains(element)) continue; + return Multisets.immutableEntry(element, entry2.getCount()); + } + return (Multiset.Entry)this.endOfData(); + } + }; + } + + @Override + int distinctElements() { + return this.elementSet().size(); + } + }; + } + + @Beta + public static Multiset difference(final Multiset multiset1, final Multiset multiset2) { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + return new AbstractMultiset(){ + + @Override + public int count(@Nullable Object element) { + int count1 = multiset1.count(element); + return count1 == 0 ? 0 : Math.max(0, count1 - multiset2.count(element)); + } + + @Override + Iterator> entryIterator() { + final Iterator iterator1 = multiset1.entrySet().iterator(); + return new AbstractIterator>(){ + + @Override + protected Multiset.Entry computeNext() { + while (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + Object element = entry1.getElement(); + int count = entry1.getCount() - multiset2.count(element); + if (count <= 0) continue; + return Multisets.immutableEntry(element, count); + } + return (Multiset.Entry)this.endOfData(); + } + }; + } + + @Override + int distinctElements() { + return Iterators.size(this.entryIterator()); + } + }; + } + + public static boolean containsOccurrences(Multiset superMultiset, Multiset subMultiset) { + Preconditions.checkNotNull(superMultiset); + Preconditions.checkNotNull(subMultiset); + for (Multiset.Entry entry : subMultiset.entrySet()) { + int superCount = superMultiset.count(entry.getElement()); + if (superCount >= entry.getCount()) continue; + return false; + } + return true; + } + + public static boolean retainOccurrences(Multiset multisetToModify, Multiset multisetToRetain) { + return Multisets.retainOccurrencesImpl(multisetToModify, multisetToRetain); + } + + private static boolean retainOccurrencesImpl(Multiset multisetToModify, Multiset occurrencesToRetain) { + Preconditions.checkNotNull(multisetToModify); + Preconditions.checkNotNull(occurrencesToRetain); + Iterator> entryIterator = multisetToModify.entrySet().iterator(); + boolean changed = false; + while (entryIterator.hasNext()) { + Multiset.Entry entry = entryIterator.next(); + int retainCount = occurrencesToRetain.count(entry.getElement()); + if (retainCount == 0) { + entryIterator.remove(); + changed = true; + continue; + } + if (retainCount >= entry.getCount()) continue; + multisetToModify.setCount(entry.getElement(), retainCount); + changed = true; + } + return changed; + } + + public static boolean removeOccurrences(Multiset multisetToModify, Iterable occurrencesToRemove) { + if (occurrencesToRemove instanceof Multiset) { + return Multisets.removeOccurrencesImpl(multisetToModify, (Multiset)occurrencesToRemove); + } + return Multisets.removeOccurrencesImpl(multisetToModify, occurrencesToRemove); + } + + private static boolean removeOccurrencesImpl(Multiset multisetToModify, Iterable occurrencesToRemove) { + Preconditions.checkNotNull(multisetToModify); + Preconditions.checkNotNull(occurrencesToRemove); + boolean changed = false; + for (Object o : occurrencesToRemove) { + changed |= multisetToModify.remove(o); + } + return changed; + } + + private static boolean removeOccurrencesImpl(Multiset multisetToModify, Multiset occurrencesToRemove) { + Preconditions.checkNotNull(multisetToModify); + Preconditions.checkNotNull(occurrencesToRemove); + boolean changed = false; + Iterator> entryIterator = multisetToModify.entrySet().iterator(); + while (entryIterator.hasNext()) { + Multiset.Entry entry = entryIterator.next(); + int removeCount = occurrencesToRemove.count(entry.getElement()); + if (removeCount >= entry.getCount()) { + entryIterator.remove(); + changed = true; + continue; + } + if (removeCount <= 0) continue; + multisetToModify.remove(entry.getElement(), removeCount); + changed = true; + } + return changed; + } + + static boolean equalsImpl(Multiset multiset, @Nullable Object object) { + if (object == multiset) { + return true; + } + if (object instanceof Multiset) { + Multiset that = (Multiset)object; + if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) { + return false; + } + for (Multiset.Entry entry : that.entrySet()) { + if (multiset.count(entry.getElement()) == entry.getCount()) continue; + return false; + } + return true; + } + return false; + } + + static boolean addAllImpl(Multiset self, Collection elements) { + if (elements.isEmpty()) { + return false; + } + if (elements instanceof Multiset) { + Multiset that = Multisets.cast(elements); + for (Multiset.Entry entry : that.entrySet()) { + self.add(entry.getElement(), entry.getCount()); + } + } else { + Iterators.addAll(self, elements.iterator()); + } + return true; + } + + static boolean removeAllImpl(Multiset self, Collection elementsToRemove) { + Collection collection = elementsToRemove instanceof Multiset ? ((Multiset)elementsToRemove).elementSet() : elementsToRemove; + return self.elementSet().removeAll(collection); + } + + static boolean retainAllImpl(Multiset self, Collection elementsToRetain) { + Preconditions.checkNotNull(elementsToRetain); + Collection collection = elementsToRetain instanceof Multiset ? ((Multiset)elementsToRetain).elementSet() : elementsToRetain; + return self.elementSet().retainAll(collection); + } + + static int setCountImpl(Multiset self, E element, int count) { + CollectPreconditions.checkNonnegative(count, "count"); + int oldCount = self.count(element); + int delta = count - oldCount; + if (delta > 0) { + self.add(element, delta); + } else if (delta < 0) { + self.remove(element, -delta); + } + return oldCount; + } + + static boolean setCountImpl(Multiset self, E element, int oldCount, int newCount) { + CollectPreconditions.checkNonnegative(oldCount, "oldCount"); + CollectPreconditions.checkNonnegative(newCount, "newCount"); + if (self.count(element) == oldCount) { + self.setCount(element, newCount); + return true; + } + return false; + } + + static Iterator iteratorImpl(Multiset multiset) { + return new MultisetIteratorImpl(multiset, multiset.entrySet().iterator()); + } + + static int sizeImpl(Multiset multiset) { + long size = 0L; + for (Multiset.Entry entry : multiset.entrySet()) { + size += (long)entry.getCount(); + } + return Ints.saturatedCast(size); + } + + static Multiset cast(Iterable iterable) { + return (Multiset)iterable; + } + + @Beta + public static ImmutableMultiset copyHighestCountFirst(Multiset multiset) { + ImmutableList> sortedEntries = DECREASING_COUNT_ORDERING.immutableSortedCopy(multiset.entrySet()); + return ImmutableMultiset.copyFromEntries(sortedEntries); + } + + static final class MultisetIteratorImpl + implements Iterator { + private final Multiset multiset; + private final Iterator> entryIterator; + private Multiset.Entry currentEntry; + private int laterCount; + private int totalCount; + private boolean canRemove; + + MultisetIteratorImpl(Multiset multiset, Iterator> entryIterator) { + this.multiset = multiset; + this.entryIterator = entryIterator; + } + + @Override + public boolean hasNext() { + return this.laterCount > 0 || this.entryIterator.hasNext(); + } + + @Override + public E next() { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + if (this.laterCount == 0) { + this.currentEntry = this.entryIterator.next(); + this.totalCount = this.laterCount = this.currentEntry.getCount(); + } + --this.laterCount; + this.canRemove = true; + return this.currentEntry.getElement(); + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.canRemove); + if (this.totalCount == 1) { + this.entryIterator.remove(); + } else { + this.multiset.remove(this.currentEntry.getElement()); + } + --this.totalCount; + this.canRemove = false; + } + } + + static abstract class EntrySet + extends Sets.ImprovedAbstractSet> { + EntrySet() { + } + + abstract Multiset multiset(); + + @Override + public boolean contains(@Nullable Object o) { + if (o instanceof Multiset.Entry) { + Multiset.Entry entry = (Multiset.Entry)o; + if (entry.getCount() <= 0) { + return false; + } + int count = this.multiset().count(entry.getElement()); + return count == entry.getCount(); + } + return false; + } + + @Override + public boolean remove(Object object) { + if (object instanceof Multiset.Entry) { + Multiset.Entry entry = (Multiset.Entry)object; + Object element = entry.getElement(); + int entryCount = entry.getCount(); + if (entryCount != 0) { + Multiset multiset = this.multiset(); + return multiset.setCount(element, entryCount, 0); + } + } + return false; + } + + @Override + public void clear() { + this.multiset().clear(); + } + } + + static abstract class ElementSet + extends Sets.ImprovedAbstractSet { + ElementSet() { + } + + abstract Multiset multiset(); + + @Override + public void clear() { + this.multiset().clear(); + } + + @Override + public boolean contains(Object o) { + return this.multiset().contains(o); + } + + @Override + public boolean containsAll(Collection c) { + return this.multiset().containsAll(c); + } + + @Override + public boolean isEmpty() { + return this.multiset().isEmpty(); + } + + @Override + public Iterator iterator() { + return new TransformedIterator, E>(this.multiset().entrySet().iterator()){ + + @Override + E transform(Multiset.Entry entry) { + return entry.getElement(); + } + }; + } + + @Override + public boolean remove(Object o) { + int count = this.multiset().count(o); + if (count > 0) { + this.multiset().remove(o, count); + return true; + } + return false; + } + + @Override + public int size() { + return this.multiset().entrySet().size(); + } + } + + static abstract class AbstractEntry + implements Multiset.Entry { + AbstractEntry() { + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Multiset.Entry) { + Multiset.Entry that = (Multiset.Entry)object; + return this.getCount() == that.getCount() && Objects.equal(this.getElement(), that.getElement()); + } + return false; + } + + @Override + public int hashCode() { + Object e = this.getElement(); + return (e == null ? 0 : e.hashCode()) ^ this.getCount(); + } + + @Override + public String toString() { + String string; + String text = String.valueOf(this.getElement()); + int n = this.getCount(); + if (n == 1) { + string = text; + } else { + String string2 = String.valueOf(String.valueOf(text)); + int n2 = n; + string = new StringBuilder(14 + string2.length()).append(string2).append(" x ").append(n2).toString(); + } + return string; + } + } + + private static final class FilteredMultiset + extends AbstractMultiset { + final Multiset unfiltered; + final Predicate predicate; + + FilteredMultiset(Multiset unfiltered, Predicate predicate) { + this.unfiltered = Preconditions.checkNotNull(unfiltered); + this.predicate = Preconditions.checkNotNull(predicate); + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.filter(this.unfiltered.iterator(), this.predicate); + } + + @Override + Set createElementSet() { + return Sets.filter(this.unfiltered.elementSet(), this.predicate); + } + + @Override + Set> createEntrySet() { + return Sets.filter(this.unfiltered.entrySet(), new Predicate>(){ + + @Override + public boolean apply(Multiset.Entry entry) { + return FilteredMultiset.this.predicate.apply(entry.getElement()); + } + }); + } + + @Override + Iterator> entryIterator() { + throw new AssertionError((Object)"should never be called"); + } + + @Override + int distinctElements() { + return this.elementSet().size(); + } + + @Override + public int count(@Nullable Object element) { + int count = this.unfiltered.count(element); + if (count > 0) { + Object e = element; + return this.predicate.apply(e) ? count : 0; + } + return 0; + } + + @Override + public int add(@Nullable E element, int occurrences) { + Preconditions.checkArgument(this.predicate.apply(element), "Element %s does not match predicate %s", element, this.predicate); + return this.unfiltered.add(element, occurrences); + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return this.count(element); + } + return this.contains(element) ? this.unfiltered.remove(element, occurrences) : 0; + } + + @Override + public void clear() { + this.elementSet().clear(); + } + } + + static final class ImmutableEntry + extends AbstractEntry + implements Serializable { + @Nullable + final E element; + final int count; + private static final long serialVersionUID = 0L; + + ImmutableEntry(@Nullable E element, int count) { + this.element = element; + this.count = count; + CollectPreconditions.checkNonnegative(count, "count"); + } + + @Override + @Nullable + public E getElement() { + return this.element; + } + + @Override + public int getCount() { + return this.count; + } + } + + static class UnmodifiableMultiset + extends ForwardingMultiset + implements Serializable { + final Multiset delegate; + transient Set elementSet; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + UnmodifiableMultiset(Multiset delegate) { + this.delegate = delegate; + } + + @Override + protected Multiset delegate() { + return this.delegate; + } + + Set createElementSet() { + return Collections.unmodifiableSet(this.delegate.elementSet()); + } + + @Override + public Set elementSet() { + Set es = this.elementSet; + return es == null ? (this.elementSet = this.createElementSet()) : es; + } + + @Override + public Set> entrySet() { + Set>> es = this.entrySet; + return es == null ? (this.entrySet = Collections.unmodifiableSet(this.delegate.entrySet())) : es; + } + + @Override + public Iterator iterator() { + return Iterators.unmodifiableIterator(this.delegate.iterator()); + } + + @Override + public boolean add(E element) { + throw new UnsupportedOperationException(); + } + + @Override + public int add(E element, int occurences) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection elementsToAdd) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object element) { + throw new UnsupportedOperationException(); + } + + @Override + public int remove(Object element, int occurrences) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection elementsToRemove) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection elementsToRetain) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public int setCount(E element, int count) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setCount(E element, int oldCount, int newCount) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/com/google/common/collect/MutableClassToInstanceMap.java b/src/com/google/common/collect/MutableClassToInstanceMap.java new file mode 100644 index 0000000..57214af --- /dev/null +++ b/src/com/google/common/collect/MutableClassToInstanceMap.java @@ -0,0 +1,50 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.ClassToInstanceMap; +import com.google.common.collect.MapConstraint; +import com.google.common.collect.MapConstraints; +import com.google.common.primitives.Primitives; +import java.util.HashMap; +import java.util.Map; + +public final class MutableClassToInstanceMap +extends MapConstraints.ConstrainedMap, B> +implements ClassToInstanceMap { + private static final MapConstraint, Object> VALUE_CAN_BE_CAST_TO_KEY = new MapConstraint, Object>(){ + + @Override + public void checkKeyValue(Class key, Object value) { + MutableClassToInstanceMap.cast(key, value); + } + }; + private static final long serialVersionUID = 0L; + + public static MutableClassToInstanceMap create() { + return new MutableClassToInstanceMap(new HashMap()); + } + + public static MutableClassToInstanceMap create(Map, B> backingMap) { + return new MutableClassToInstanceMap(backingMap); + } + + private MutableClassToInstanceMap(Map, B> delegate) { + super(delegate, VALUE_CAN_BE_CAST_TO_KEY); + } + + @Override + public T putInstance(Class type, T value) { + return MutableClassToInstanceMap.cast(type, this.put(type, value)); + } + + @Override + public T getInstance(Class type) { + return MutableClassToInstanceMap.cast(type, this.get(type)); + } + + private static T cast(Class type, B value) { + return Primitives.wrap(type).cast(value); + } +} diff --git a/src/com/google/common/collect/NaturalOrdering.java b/src/com/google/common/collect/NaturalOrdering.java new file mode 100644 index 0000000..e139fbc --- /dev/null +++ b/src/com/google/common/collect/NaturalOrdering.java @@ -0,0 +1,41 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Ordering; +import com.google.common.collect.ReverseNaturalOrdering; +import java.io.Serializable; + +@GwtCompatible(serializable=true) +final class NaturalOrdering +extends Ordering +implements Serializable { + static final NaturalOrdering INSTANCE = new NaturalOrdering(); + private static final long serialVersionUID = 0L; + + @Override + public int compare(Comparable left, Comparable right) { + Preconditions.checkNotNull(left); + Preconditions.checkNotNull(right); + return left.compareTo(right); + } + + @Override + public Ordering reverse() { + return ReverseNaturalOrdering.INSTANCE; + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "Ordering.natural()"; + } + + private NaturalOrdering() { + } +} diff --git a/src/com/google/common/collect/NullsFirstOrdering.java b/src/com/google/common/collect/NullsFirstOrdering.java new file mode 100644 index 0000000..e239dbf --- /dev/null +++ b/src/com/google/common/collect/NullsFirstOrdering.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class NullsFirstOrdering +extends Ordering +implements Serializable { + final Ordering ordering; + private static final long serialVersionUID = 0L; + + NullsFirstOrdering(Ordering ordering) { + this.ordering = ordering; + } + + @Override + public int compare(@Nullable T left, @Nullable T right) { + if (left == right) { + return 0; + } + if (left == null) { + return -1; + } + if (right == null) { + return 1; + } + return this.ordering.compare(left, right); + } + + @Override + public Ordering reverse() { + return this.ordering.reverse().nullsLast(); + } + + @Override + public Ordering nullsFirst() { + return this; + } + + @Override + public Ordering nullsLast() { + return this.ordering.nullsLast(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof NullsFirstOrdering) { + NullsFirstOrdering that = (NullsFirstOrdering)object; + return this.ordering.equals(that.ordering); + } + return false; + } + + public int hashCode() { + return this.ordering.hashCode() ^ 0x39153A74; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.ordering)); + return new StringBuilder(13 + string.length()).append(string).append(".nullsFirst()").toString(); + } +} diff --git a/src/com/google/common/collect/NullsLastOrdering.java b/src/com/google/common/collect/NullsLastOrdering.java new file mode 100644 index 0000000..d3c0c09 --- /dev/null +++ b/src/com/google/common/collect/NullsLastOrdering.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class NullsLastOrdering +extends Ordering +implements Serializable { + final Ordering ordering; + private static final long serialVersionUID = 0L; + + NullsLastOrdering(Ordering ordering) { + this.ordering = ordering; + } + + @Override + public int compare(@Nullable T left, @Nullable T right) { + if (left == right) { + return 0; + } + if (left == null) { + return 1; + } + if (right == null) { + return -1; + } + return this.ordering.compare(left, right); + } + + @Override + public Ordering reverse() { + return this.ordering.reverse().nullsFirst(); + } + + @Override + public Ordering nullsFirst() { + return this.ordering.nullsFirst(); + } + + @Override + public Ordering nullsLast() { + return this; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof NullsLastOrdering) { + NullsLastOrdering that = (NullsLastOrdering)object; + return this.ordering.equals(that.ordering); + } + return false; + } + + public int hashCode() { + return this.ordering.hashCode() ^ 0xC9177248; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.ordering)); + return new StringBuilder(12 + string.length()).append(string).append(".nullsLast()").toString(); + } +} diff --git a/src/com/google/common/collect/ObjectArrays.java b/src/com/google/common/collect/ObjectArrays.java new file mode 100644 index 0000000..bb5ba3f --- /dev/null +++ b/src/com/google/common/collect/ObjectArrays.java @@ -0,0 +1,126 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Platform; +import java.lang.reflect.Array; +import java.util.Collection; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class ObjectArrays { + static final Object[] EMPTY_ARRAY = new Object[0]; + + private ObjectArrays() { + } + + @GwtIncompatible(value="Array.newInstance(Class, int)") + public static T[] newArray(Class type, int length) { + return (Object[])Array.newInstance(type, length); + } + + public static T[] newArray(T[] reference, int length) { + return Platform.newArray(reference, length); + } + + @GwtIncompatible(value="Array.newInstance(Class, int)") + public static T[] concat(T[] first, T[] second, Class type) { + T[] result = ObjectArrays.newArray(type, first.length + second.length); + System.arraycopy(first, 0, result, 0, first.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } + + public static T[] concat(@Nullable T element, T[] array) { + T[] result = ObjectArrays.newArray(array, array.length + 1); + result[0] = element; + System.arraycopy(array, 0, result, 1, array.length); + return result; + } + + public static T[] concat(T[] array, @Nullable T element) { + T[] result = ObjectArrays.arraysCopyOf(array, array.length + 1); + result[array.length] = element; + return result; + } + + static T[] arraysCopyOf(T[] original, int newLength) { + T[] copy = ObjectArrays.newArray(original, newLength); + System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); + return copy; + } + + static T[] toArrayImpl(Collection c, T[] array) { + int size = c.size(); + if (array.length < size) { + array = ObjectArrays.newArray(array, size); + } + ObjectArrays.fillArray(c, array); + if (array.length > size) { + array[size] = null; + } + return array; + } + + static T[] toArrayImpl(Object[] src, int offset, int len, T[] dst) { + Preconditions.checkPositionIndexes(offset, offset + len, src.length); + if (dst.length < len) { + dst = ObjectArrays.newArray(dst, len); + } else if (dst.length > len) { + dst[len] = null; + } + System.arraycopy(src, offset, dst, 0, len); + return dst; + } + + static Object[] toArrayImpl(Collection c) { + return ObjectArrays.fillArray(c, new Object[c.size()]); + } + + static Object[] copyAsObjectArray(Object[] elements, int offset, int length) { + Preconditions.checkPositionIndexes(offset, offset + length, elements.length); + if (length == 0) { + return EMPTY_ARRAY; + } + Object[] result = new Object[length]; + System.arraycopy(elements, offset, result, 0, length); + return result; + } + + private static Object[] fillArray(Iterable elements, Object[] array) { + int i = 0; + for (Object element : elements) { + array[i++] = element; + } + return array; + } + + static void swap(Object[] array, int i, int j) { + Object temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + static Object[] checkElementsNotNull(Object ... array) { + return ObjectArrays.checkElementsNotNull(array, array.length); + } + + static Object[] checkElementsNotNull(Object[] array, int length) { + for (int i = 0; i < length; ++i) { + ObjectArrays.checkElementNotNull(array[i], i); + } + return array; + } + + static Object checkElementNotNull(Object element, int index) { + if (element == null) { + int n = index; + throw new NullPointerException(new StringBuilder(20).append("at index ").append(n).toString()); + } + return element; + } +} diff --git a/src/com/google/common/collect/Ordering.java b/src/com/google/common/collect/Ordering.java new file mode 100644 index 0000000..e3c1e96 --- /dev/null +++ b/src/com/google/common/collect/Ordering.java @@ -0,0 +1,385 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.AllEqualOrdering; +import com.google.common.collect.ByFunctionOrdering; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ComparatorOrdering; +import com.google.common.collect.CompoundOrdering; +import com.google.common.collect.ExplicitOrdering; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.LexicographicalOrdering; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.common.collect.NaturalOrdering; +import com.google.common.collect.NullsFirstOrdering; +import com.google.common.collect.NullsLastOrdering; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Platform; +import com.google.common.collect.ReverseOrdering; +import com.google.common.collect.UsingToStringOrdering; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract class Ordering +implements Comparator { + static final int LEFT_IS_GREATER = 1; + static final int RIGHT_IS_GREATER = -1; + + @GwtCompatible(serializable=true) + public static Ordering natural() { + return NaturalOrdering.INSTANCE; + } + + @GwtCompatible(serializable=true) + public static Ordering from(Comparator comparator) { + return comparator instanceof Ordering ? (Ordering)comparator : new ComparatorOrdering(comparator); + } + + @Deprecated + @GwtCompatible(serializable=true) + public static Ordering from(Ordering ordering) { + return Preconditions.checkNotNull(ordering); + } + + @GwtCompatible(serializable=true) + public static Ordering explicit(List valuesInOrder) { + return new ExplicitOrdering(valuesInOrder); + } + + @GwtCompatible(serializable=true) + public static Ordering explicit(T leastValue, T ... remainingValuesInOrder) { + return Ordering.explicit(Lists.asList(leastValue, remainingValuesInOrder)); + } + + @GwtCompatible(serializable=true) + public static Ordering allEqual() { + return AllEqualOrdering.INSTANCE; + } + + @GwtCompatible(serializable=true) + public static Ordering usingToString() { + return UsingToStringOrdering.INSTANCE; + } + + public static Ordering arbitrary() { + return ArbitraryOrderingHolder.ARBITRARY_ORDERING; + } + + protected Ordering() { + } + + @GwtCompatible(serializable=true) + public Ordering reverse() { + return new ReverseOrdering(this); + } + + @GwtCompatible(serializable=true) + public Ordering nullsFirst() { + return new NullsFirstOrdering(this); + } + + @GwtCompatible(serializable=true) + public Ordering nullsLast() { + return new NullsLastOrdering(this); + } + + @GwtCompatible(serializable=true) + public Ordering onResultOf(Function function) { + return new ByFunctionOrdering(function, this); + } + + Ordering> onKeys() { + return this.onResultOf(Maps.keyFunction()); + } + + @GwtCompatible(serializable=true) + public Ordering compound(Comparator secondaryComparator) { + return new CompoundOrdering(this, Preconditions.checkNotNull(secondaryComparator)); + } + + @GwtCompatible(serializable=true) + public static Ordering compound(Iterable> comparators) { + return new CompoundOrdering(comparators); + } + + @GwtCompatible(serializable=true) + public Ordering> lexicographical() { + return new LexicographicalOrdering(this); + } + + @Override + public abstract int compare(@Nullable T var1, @Nullable T var2); + + public E min(Iterator iterator) { + E minSoFar = iterator.next(); + while (iterator.hasNext()) { + minSoFar = this.min(minSoFar, iterator.next()); + } + return minSoFar; + } + + public E min(Iterable iterable) { + return this.min(iterable.iterator()); + } + + public E min(@Nullable E a, @Nullable E b) { + return this.compare(a, b) <= 0 ? a : b; + } + + public E min(@Nullable E a, @Nullable E b, @Nullable E c, E ... rest) { + E minSoFar = this.min(this.min(a, b), c); + for (E r : rest) { + minSoFar = this.min(minSoFar, r); + } + return minSoFar; + } + + public E max(Iterator iterator) { + E maxSoFar = iterator.next(); + while (iterator.hasNext()) { + maxSoFar = this.max(maxSoFar, iterator.next()); + } + return maxSoFar; + } + + public E max(Iterable iterable) { + return this.max(iterable.iterator()); + } + + public E max(@Nullable E a, @Nullable E b) { + return this.compare(a, b) >= 0 ? a : b; + } + + public E max(@Nullable E a, @Nullable E b, @Nullable E c, E ... rest) { + E maxSoFar = this.max(this.max(a, b), c); + for (E r : rest) { + maxSoFar = this.max(maxSoFar, r); + } + return maxSoFar; + } + + public List leastOf(Iterable iterable, int k) { + Collection collection; + if (iterable instanceof Collection && (long)(collection = (Collection)iterable).size() <= 2L * (long)k) { + Object[] array = collection.toArray(); + Arrays.sort(array, this); + if (array.length > k) { + array = ObjectArrays.arraysCopyOf(array, k); + } + return Collections.unmodifiableList(Arrays.asList(array)); + } + return this.leastOf(iterable.iterator(), k); + } + + public List leastOf(Iterator elements, int k) { + E e; + Preconditions.checkNotNull(elements); + CollectPreconditions.checkNonnegative(k, "k"); + if (k == 0 || !elements.hasNext()) { + return ImmutableList.of(); + } + if (k >= 0x3FFFFFFF) { + ArrayList list = Lists.newArrayList(elements); + Collections.sort(list, this); + if (list.size() > k) { + list.subList(k, list.size()).clear(); + } + list.trimToSize(); + return Collections.unmodifiableList(list); + } + int bufferCap = k * 2; + Object[] buffer = new Object[bufferCap]; + Object threshold = elements.next(); + buffer[0] = threshold; + int bufferSize = 1; + while (bufferSize < k && elements.hasNext()) { + e = elements.next(); + buffer[bufferSize++] = e; + threshold = this.max(threshold, e); + } + while (elements.hasNext()) { + e = elements.next(); + if (this.compare(e, threshold) >= 0) continue; + buffer[bufferSize++] = e; + if (bufferSize != bufferCap) continue; + int left = 0; + int right = bufferCap - 1; + int minThresholdPosition = 0; + while (left < right) { + int pivotIndex = left + right + 1 >>> 1; + int pivotNewIndex = this.partition(buffer, left, right, pivotIndex); + if (pivotNewIndex > k) { + right = pivotNewIndex - 1; + continue; + } + if (pivotNewIndex >= k) break; + left = Math.max(pivotNewIndex, left + 1); + minThresholdPosition = pivotNewIndex; + } + bufferSize = k; + threshold = buffer[minThresholdPosition]; + for (int i = minThresholdPosition + 1; i < bufferSize; ++i) { + threshold = this.max(threshold, buffer[i]); + } + } + Arrays.sort(buffer, 0, bufferSize, this); + bufferSize = Math.min(bufferSize, k); + return Collections.unmodifiableList(Arrays.asList(ObjectArrays.arraysCopyOf(buffer, bufferSize))); + } + + private int partition(E[] values, int left, int right, int pivotIndex) { + E pivotValue = values[pivotIndex]; + values[pivotIndex] = values[right]; + values[right] = pivotValue; + int storeIndex = left; + for (int i = left; i < right; ++i) { + if (this.compare(values[i], pivotValue) >= 0) continue; + ObjectArrays.swap(values, storeIndex, i); + ++storeIndex; + } + ObjectArrays.swap(values, right, storeIndex); + return storeIndex; + } + + public List greatestOf(Iterable iterable, int k) { + return this.reverse().leastOf(iterable, k); + } + + public List greatestOf(Iterator iterator, int k) { + return this.reverse().leastOf(iterator, k); + } + + public List sortedCopy(Iterable elements) { + Object[] array = Iterables.toArray(elements); + Arrays.sort(array, this); + return Lists.newArrayList(Arrays.asList(array)); + } + + public ImmutableList immutableSortedCopy(Iterable elements) { + Object[] array; + for (Object e : array = Iterables.toArray(elements)) { + Preconditions.checkNotNull(e); + } + Arrays.sort(array, this); + return ImmutableList.asImmutableList(array); + } + + public boolean isOrdered(Iterable iterable) { + Iterator it = iterable.iterator(); + if (it.hasNext()) { + T prev = it.next(); + while (it.hasNext()) { + T next = it.next(); + if (this.compare(prev, next) > 0) { + return false; + } + prev = next; + } + } + return true; + } + + public boolean isStrictlyOrdered(Iterable iterable) { + Iterator it = iterable.iterator(); + if (it.hasNext()) { + T prev = it.next(); + while (it.hasNext()) { + T next = it.next(); + if (this.compare(prev, next) >= 0) { + return false; + } + prev = next; + } + } + return true; + } + + public int binarySearch(List sortedList, @Nullable T key) { + return Collections.binarySearch(sortedList, key, this); + } + + @VisibleForTesting + static class IncomparableValueException + extends ClassCastException { + final Object value; + private static final long serialVersionUID = 0L; + + IncomparableValueException(Object value) { + String string = String.valueOf(String.valueOf(value)); + super(new StringBuilder(22 + string.length()).append("Cannot compare value: ").append(string).toString()); + this.value = value; + } + } + + @VisibleForTesting + static class ArbitraryOrdering + extends Ordering { + private Map uids = Platform.tryWeakKeys(new MapMaker()).makeComputingMap(new Function(){ + final AtomicInteger counter = new AtomicInteger(0); + + @Override + public Integer apply(Object from) { + return this.counter.getAndIncrement(); + } + }); + + ArbitraryOrdering() { + } + + @Override + public int compare(Object left, Object right) { + int rightCode; + if (left == right) { + return 0; + } + if (left == null) { + return -1; + } + if (right == null) { + return 1; + } + int leftCode = this.identityHashCode(left); + if (leftCode != (rightCode = this.identityHashCode(right))) { + return leftCode < rightCode ? -1 : 1; + } + int result = this.uids.get(left).compareTo(this.uids.get(right)); + if (result == 0) { + throw new AssertionError(); + } + return result; + } + + public String toString() { + return "Ordering.arbitrary()"; + } + + int identityHashCode(Object object) { + return System.identityHashCode(object); + } + } + + private static class ArbitraryOrderingHolder { + static final Ordering ARBITRARY_ORDERING = new ArbitraryOrdering(); + + private ArbitraryOrderingHolder() { + } + } +} diff --git a/src/com/google/common/collect/PeekingIterator.java b/src/com/google/common/collect/PeekingIterator.java new file mode 100644 index 0000000..9d04ddd --- /dev/null +++ b/src/com/google/common/collect/PeekingIterator.java @@ -0,0 +1,19 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; + +@GwtCompatible +public interface PeekingIterator +extends Iterator { + public E peek(); + + @Override + public E next(); + + @Override + public void remove(); +} diff --git a/src/com/google/common/collect/Platform.java b/src/com/google/common/collect/Platform.java new file mode 100644 index 0000000..509778c --- /dev/null +++ b/src/com/google/common/collect/Platform.java @@ -0,0 +1,55 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.lang.reflect.Array; +import java.util.Collections; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; + +@GwtCompatible(emulated=true) +final class Platform { + static T[] newArray(T[] reference, int length) { + Class type = reference.getClass().getComponentType(); + Object[] result = (Object[])Array.newInstance(type, length); + return result; + } + + static Set newSetFromMap(Map map) { + return Collections.newSetFromMap(map); + } + + static MapMaker tryWeakKeys(MapMaker mapMaker) { + return mapMaker.weakKeys(); + } + + static SortedMap mapsTransformEntriesSortedMap(SortedMap fromMap, Maps.EntryTransformer transformer) { + return fromMap instanceof NavigableMap ? Maps.transformEntries((NavigableMap)fromMap, transformer) : Maps.transformEntriesIgnoreNavigable(fromMap, transformer); + } + + static SortedMap mapsAsMapSortedSet(SortedSet set, Function function) { + return set instanceof NavigableSet ? Maps.asMap((NavigableSet)set, function) : Maps.asMapSortedIgnoreNavigable(set, function); + } + + static SortedSet setsFilterSortedSet(SortedSet set, Predicate predicate) { + return set instanceof NavigableSet ? Sets.filter((NavigableSet)set, predicate) : Sets.filterSortedIgnoreNavigable(set, predicate); + } + + static SortedMap mapsFilterSortedMap(SortedMap map, Predicate> predicate) { + return map instanceof NavigableMap ? Maps.filterEntries((NavigableMap)map, predicate) : Maps.filterSortedIgnoreNavigable(map, predicate); + } + + private Platform() { + } +} diff --git a/src/com/google/common/collect/Queues.java b/src/com/google/common/collect/Queues.java new file mode 100644 index 0000000..a5348fe --- /dev/null +++ b/src/com/google/common/collect/Queues.java @@ -0,0 +1,183 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.Iterables; +import com.google.common.collect.Synchronized; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; + +public final class Queues { + private Queues() { + } + + public static ArrayBlockingQueue newArrayBlockingQueue(int capacity) { + return new ArrayBlockingQueue(capacity); + } + + public static ArrayDeque newArrayDeque() { + return new ArrayDeque(); + } + + public static ArrayDeque newArrayDeque(Iterable elements) { + if (elements instanceof Collection) { + return new ArrayDeque(Collections2.cast(elements)); + } + ArrayDeque deque = new ArrayDeque(); + Iterables.addAll(deque, elements); + return deque; + } + + public static ConcurrentLinkedQueue newConcurrentLinkedQueue() { + return new ConcurrentLinkedQueue(); + } + + public static ConcurrentLinkedQueue newConcurrentLinkedQueue(Iterable elements) { + if (elements instanceof Collection) { + return new ConcurrentLinkedQueue(Collections2.cast(elements)); + } + ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + public static LinkedBlockingDeque newLinkedBlockingDeque() { + return new LinkedBlockingDeque(); + } + + public static LinkedBlockingDeque newLinkedBlockingDeque(int capacity) { + return new LinkedBlockingDeque(capacity); + } + + public static LinkedBlockingDeque newLinkedBlockingDeque(Iterable elements) { + if (elements instanceof Collection) { + return new LinkedBlockingDeque(Collections2.cast(elements)); + } + LinkedBlockingDeque deque = new LinkedBlockingDeque(); + Iterables.addAll(deque, elements); + return deque; + } + + public static LinkedBlockingQueue newLinkedBlockingQueue() { + return new LinkedBlockingQueue(); + } + + public static LinkedBlockingQueue newLinkedBlockingQueue(int capacity) { + return new LinkedBlockingQueue(capacity); + } + + public static LinkedBlockingQueue newLinkedBlockingQueue(Iterable elements) { + if (elements instanceof Collection) { + return new LinkedBlockingQueue(Collections2.cast(elements)); + } + LinkedBlockingQueue queue = new LinkedBlockingQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + public static PriorityBlockingQueue newPriorityBlockingQueue() { + return new PriorityBlockingQueue(); + } + + public static PriorityBlockingQueue newPriorityBlockingQueue(Iterable elements) { + if (elements instanceof Collection) { + return new PriorityBlockingQueue(Collections2.cast(elements)); + } + PriorityBlockingQueue queue = new PriorityBlockingQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + public static PriorityQueue newPriorityQueue() { + return new PriorityQueue(); + } + + public static PriorityQueue newPriorityQueue(Iterable elements) { + if (elements instanceof Collection) { + return new PriorityQueue(Collections2.cast(elements)); + } + PriorityQueue queue = new PriorityQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + public static SynchronousQueue newSynchronousQueue() { + return new SynchronousQueue(); + } + + @Beta + public static int drain(BlockingQueue q, Collection buffer, int numElements, long timeout, TimeUnit unit) throws InterruptedException { + Preconditions.checkNotNull(buffer); + long deadline = System.nanoTime() + unit.toNanos(timeout); + int added = 0; + while (added < numElements) { + if ((added += q.drainTo(buffer, numElements - added)) >= numElements) continue; + E e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS); + if (e == null) break; + buffer.add(e); + ++added; + } + return added; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Beta + public static int drainUninterruptibly(BlockingQueue q, Collection buffer, int numElements, long timeout, TimeUnit unit) { + Preconditions.checkNotNull(buffer); + long deadline = System.nanoTime() + unit.toNanos(timeout); + int added = 0; + boolean interrupted = false; + try { + while (added < numElements) { + E e; + if ((added += q.drainTo(buffer, numElements - added)) >= numElements) continue; + while (true) { + try { + e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS); + } + catch (InterruptedException ex) { + interrupted = true; + continue; + } + break; + } + if (e == null) { + break; + } + buffer.add(e); + ++added; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + return added; + } + + public static Queue synchronizedQueue(Queue queue) { + return Synchronized.queue(queue, null); + } + + public static Deque synchronizedDeque(Deque deque) { + return Synchronized.deque(deque, null); + } +} diff --git a/src/com/google/common/collect/Range.java b/src/com/google/common/collect/Range.java new file mode 100644 index 0000000..f81c974 --- /dev/null +++ b/src/com/google/common/collect/Range.java @@ -0,0 +1,301 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.BoundType; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.Cut; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.Iterables; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Range +implements Predicate, +Serializable { + private static final Function LOWER_BOUND_FN = new Function(){ + + @Override + public Cut apply(Range range) { + return range.lowerBound; + } + }; + private static final Function UPPER_BOUND_FN = new Function(){ + + @Override + public Cut apply(Range range) { + return range.upperBound; + } + }; + static final Ordering> RANGE_LEX_ORDERING = new Ordering>(){ + + @Override + public int compare(Range left, Range right) { + return ComparisonChain.start().compare(left.lowerBound, right.lowerBound).compare(left.upperBound, right.upperBound).result(); + } + }; + private static final Range ALL = new Range(Cut.belowAll(), Cut.aboveAll()); + final Cut lowerBound; + final Cut upperBound; + private static final long serialVersionUID = 0L; + + static > Function, Cut> lowerBoundFn() { + return LOWER_BOUND_FN; + } + + static > Function, Cut> upperBoundFn() { + return UPPER_BOUND_FN; + } + + static > Range create(Cut lowerBound, Cut upperBound) { + return new Range(lowerBound, upperBound); + } + + public static > Range open(C lower, C upper) { + return Range.create(Cut.aboveValue(lower), Cut.belowValue(upper)); + } + + public static > Range closed(C lower, C upper) { + return Range.create(Cut.belowValue(lower), Cut.aboveValue(upper)); + } + + public static > Range closedOpen(C lower, C upper) { + return Range.create(Cut.belowValue(lower), Cut.belowValue(upper)); + } + + public static > Range openClosed(C lower, C upper) { + return Range.create(Cut.aboveValue(lower), Cut.aboveValue(upper)); + } + + public static > Range range(C lower, BoundType lowerType, C upper, BoundType upperType) { + Preconditions.checkNotNull(lowerType); + Preconditions.checkNotNull(upperType); + Cut lowerBound = lowerType == BoundType.OPEN ? Cut.aboveValue(lower) : Cut.belowValue(lower); + Cut upperBound = upperType == BoundType.OPEN ? Cut.belowValue(upper) : Cut.aboveValue(upper); + return Range.create(lowerBound, upperBound); + } + + public static > Range lessThan(C endpoint) { + return Range.create(Cut.belowAll(), Cut.belowValue(endpoint)); + } + + public static > Range atMost(C endpoint) { + return Range.create(Cut.belowAll(), Cut.aboveValue(endpoint)); + } + + public static > Range upTo(C endpoint, BoundType boundType) { + switch (boundType) { + case OPEN: { + return Range.lessThan(endpoint); + } + case CLOSED: { + return Range.atMost(endpoint); + } + } + throw new AssertionError(); + } + + public static > Range greaterThan(C endpoint) { + return Range.create(Cut.aboveValue(endpoint), Cut.aboveAll()); + } + + public static > Range atLeast(C endpoint) { + return Range.create(Cut.belowValue(endpoint), Cut.aboveAll()); + } + + public static > Range downTo(C endpoint, BoundType boundType) { + switch (boundType) { + case OPEN: { + return Range.greaterThan(endpoint); + } + case CLOSED: { + return Range.atLeast(endpoint); + } + } + throw new AssertionError(); + } + + public static > Range all() { + return ALL; + } + + public static > Range singleton(C value) { + return Range.closed(value, value); + } + + public static > Range encloseAll(Iterable values) { + Comparable min; + Preconditions.checkNotNull(values); + if (values instanceof ContiguousSet) { + return ((ContiguousSet)values).range(); + } + Iterator valueIterator = values.iterator(); + Comparable max = min = (Comparable)Preconditions.checkNotNull(valueIterator.next()); + while (valueIterator.hasNext()) { + Comparable value = (Comparable)Preconditions.checkNotNull(valueIterator.next()); + min = Ordering.natural().min(min, value); + max = Ordering.natural().max(max, value); + } + return Range.closed(min, max); + } + + private Range(Cut lowerBound, Cut upperBound) { + if (lowerBound.compareTo(upperBound) > 0 || lowerBound == Cut.aboveAll() || upperBound == Cut.belowAll()) { + String string = String.valueOf(Range.toString(lowerBound, upperBound)); + throw new IllegalArgumentException(string.length() != 0 ? "Invalid range: ".concat(string) : new String("Invalid range: ")); + } + this.lowerBound = Preconditions.checkNotNull(lowerBound); + this.upperBound = Preconditions.checkNotNull(upperBound); + } + + public boolean hasLowerBound() { + return this.lowerBound != Cut.belowAll(); + } + + public C lowerEndpoint() { + return this.lowerBound.endpoint(); + } + + public BoundType lowerBoundType() { + return this.lowerBound.typeAsLowerBound(); + } + + public boolean hasUpperBound() { + return this.upperBound != Cut.aboveAll(); + } + + public C upperEndpoint() { + return this.upperBound.endpoint(); + } + + public BoundType upperBoundType() { + return this.upperBound.typeAsUpperBound(); + } + + public boolean isEmpty() { + return this.lowerBound.equals(this.upperBound); + } + + public boolean contains(C value) { + Preconditions.checkNotNull(value); + return this.lowerBound.isLessThan(value) && !this.upperBound.isLessThan(value); + } + + @Override + @Deprecated + public boolean apply(C input) { + return this.contains(input); + } + + public boolean containsAll(Iterable values) { + if (Iterables.isEmpty(values)) { + return true; + } + if (values instanceof SortedSet) { + SortedSet set = Range.cast(values); + Comparator comparator = set.comparator(); + if (Ordering.natural().equals(comparator) || comparator == null) { + return this.contains((Comparable)set.first()) && this.contains((Comparable)set.last()); + } + } + for (Comparable value : values) { + if (this.contains(value)) continue; + return false; + } + return true; + } + + public boolean encloses(Range other) { + return this.lowerBound.compareTo(other.lowerBound) <= 0 && this.upperBound.compareTo(other.upperBound) >= 0; + } + + public boolean isConnected(Range other) { + return this.lowerBound.compareTo(other.upperBound) <= 0 && other.lowerBound.compareTo(this.upperBound) <= 0; + } + + public Range intersection(Range connectedRange) { + int lowerCmp = this.lowerBound.compareTo(connectedRange.lowerBound); + int upperCmp = this.upperBound.compareTo(connectedRange.upperBound); + if (lowerCmp >= 0 && upperCmp <= 0) { + return this; + } + if (lowerCmp <= 0 && upperCmp >= 0) { + return connectedRange; + } + Cut newLower = lowerCmp >= 0 ? this.lowerBound : connectedRange.lowerBound; + Cut newUpper = upperCmp <= 0 ? this.upperBound : connectedRange.upperBound; + return Range.create(newLower, newUpper); + } + + public Range span(Range other) { + int lowerCmp = this.lowerBound.compareTo(other.lowerBound); + int upperCmp = this.upperBound.compareTo(other.upperBound); + if (lowerCmp <= 0 && upperCmp >= 0) { + return this; + } + if (lowerCmp >= 0 && upperCmp <= 0) { + return other; + } + Cut newLower = lowerCmp <= 0 ? this.lowerBound : other.lowerBound; + Cut newUpper = upperCmp >= 0 ? this.upperBound : other.upperBound; + return Range.create(newLower, newUpper); + } + + public Range canonical(DiscreteDomain domain) { + Preconditions.checkNotNull(domain); + Cut lower = this.lowerBound.canonical(domain); + Cut upper = this.upperBound.canonical(domain); + return lower == this.lowerBound && upper == this.upperBound ? this : Range.create(lower, upper); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof Range) { + Range other = (Range)object; + return this.lowerBound.equals(other.lowerBound) && this.upperBound.equals(other.upperBound); + } + return false; + } + + public int hashCode() { + return this.lowerBound.hashCode() * 31 + this.upperBound.hashCode(); + } + + public String toString() { + return Range.toString(this.lowerBound, this.upperBound); + } + + private static String toString(Cut lowerBound, Cut upperBound) { + StringBuilder sb = new StringBuilder(16); + lowerBound.describeAsLowerBound(sb); + sb.append('\u2025'); + upperBound.describeAsUpperBound(sb); + return sb.toString(); + } + + private static SortedSet cast(Iterable iterable) { + return (SortedSet)iterable; + } + + Object readResolve() { + if (this.equals(ALL)) { + return Range.all(); + } + return this; + } + + static int compareOrThrow(Comparable left, Comparable right) { + return left.compareTo(right); + } +} diff --git a/src/com/google/common/collect/RangeMap.java b/src/com/google/common/collect/RangeMap.java new file mode 100644 index 0000000..f73e1ec --- /dev/null +++ b/src/com/google/common/collect/RangeMap.java @@ -0,0 +1,38 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Range; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +public interface RangeMap { + @Nullable + public V get(K var1); + + @Nullable + public Map.Entry, V> getEntry(K var1); + + public Range span(); + + public void put(Range var1, V var2); + + public void putAll(RangeMap var1); + + public void clear(); + + public void remove(Range var1); + + public Map, V> asMapOfRanges(); + + public RangeMap subRangeMap(Range var1); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + + public String toString(); +} diff --git a/src/com/google/common/collect/RangeSet.java b/src/com/google/common/collect/RangeSet.java new file mode 100644 index 0000000..d39ad54 --- /dev/null +++ b/src/com/google/common/collect/RangeSet.java @@ -0,0 +1,46 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Range; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +public interface RangeSet { + public boolean contains(C var1); + + public Range rangeContaining(C var1); + + public boolean encloses(Range var1); + + public boolean enclosesAll(RangeSet var1); + + public boolean isEmpty(); + + public Range span(); + + public Set> asRanges(); + + public RangeSet complement(); + + public RangeSet subRangeSet(Range var1); + + public void add(Range var1); + + public void remove(Range var1); + + public void clear(); + + public void addAll(RangeSet var1); + + public void removeAll(RangeSet var1); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + + public String toString(); +} diff --git a/src/com/google/common/collect/RegularContiguousSet.java b/src/com/google/common/collect/RegularContiguousSet.java new file mode 100644 index 0000000..58af3f4 --- /dev/null +++ b/src/com/google/common/collect/RegularContiguousSet.java @@ -0,0 +1,203 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractSequentialIterator; +import com.google.common.collect.BoundType; +import com.google.common.collect.Collections2; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.DiscreteDomain; +import com.google.common.collect.EmptyContiguousSet; +import com.google.common.collect.Ordering; +import com.google.common.collect.Range; +import com.google.common.collect.Sets; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Collection; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class RegularContiguousSet +extends ContiguousSet { + private final Range range; + private static final long serialVersionUID = 0L; + + RegularContiguousSet(Range range, DiscreteDomain domain) { + super(domain); + this.range = range; + } + + private ContiguousSet intersectionInCurrentDomain(Range other) { + return this.range.isConnected(other) ? ContiguousSet.create(this.range.intersection(other), this.domain) : new EmptyContiguousSet(this.domain); + } + + @Override + ContiguousSet headSetImpl(C toElement, boolean inclusive) { + return this.intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive))); + } + + @Override + ContiguousSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) { + if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) { + return new EmptyContiguousSet(this.domain); + } + return this.intersectionInCurrentDomain(Range.range(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + @Override + ContiguousSet tailSetImpl(C fromElement, boolean inclusive) { + return this.intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive))); + } + + @Override + @GwtIncompatible(value="not used by GWT emulation") + int indexOf(Object target) { + return this.contains(target) ? (int)this.domain.distance(this.first(), (Comparable)target) : -1; + } + + @Override + public UnmodifiableIterator iterator() { + return new AbstractSequentialIterator((Comparable)this.first()){ + final C last; + { + this.last = RegularContiguousSet.this.last(); + } + + @Override + protected C computeNext(C previous) { + return RegularContiguousSet.equalsOrThrow(previous, this.last) ? null : (Object)RegularContiguousSet.this.domain.next(previous); + } + }; + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return new AbstractSequentialIterator((Comparable)this.last()){ + final C first; + { + this.first = RegularContiguousSet.this.first(); + } + + @Override + protected C computeNext(C previous) { + return RegularContiguousSet.equalsOrThrow(previous, this.first) ? null : (Object)RegularContiguousSet.this.domain.previous(previous); + } + }; + } + + private static boolean equalsOrThrow(Comparable left, @Nullable Comparable right) { + return right != null && Range.compareOrThrow(left, right) == 0; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public C first() { + return this.range.lowerBound.leastValueAbove(this.domain); + } + + @Override + public C last() { + return this.range.upperBound.greatestValueBelow(this.domain); + } + + @Override + public int size() { + long distance = this.domain.distance(this.first(), this.last()); + return distance >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)distance + 1; + } + + @Override + public boolean contains(@Nullable Object object) { + if (object == null) { + return false; + } + try { + return this.range.contains((Comparable)object); + } + catch (ClassCastException e) { + return false; + } + } + + @Override + public boolean containsAll(Collection targets) { + return Collections2.containsAllImpl(this, targets); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public ContiguousSet intersection(ContiguousSet other) { + Comparable upperEndpoint; + Preconditions.checkNotNull(other); + Preconditions.checkArgument(this.domain.equals(other.domain)); + if (other.isEmpty()) { + return other; + } + Comparable lowerEndpoint = (Comparable)Ordering.natural().max(this.first(), other.first()); + return lowerEndpoint.compareTo(upperEndpoint = (Comparable)Ordering.natural().min(this.last(), other.last())) < 0 ? ContiguousSet.create(Range.closed(lowerEndpoint, upperEndpoint), this.domain) : new EmptyContiguousSet(this.domain); + } + + @Override + public Range range() { + return this.range(BoundType.CLOSED, BoundType.CLOSED); + } + + @Override + public Range range(BoundType lowerBoundType, BoundType upperBoundType) { + return Range.create(this.range.lowerBound.withLowerBoundType(lowerBoundType, this.domain), this.range.upperBound.withUpperBoundType(upperBoundType, this.domain)); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof RegularContiguousSet) { + RegularContiguousSet that = (RegularContiguousSet)object; + if (this.domain.equals(that.domain)) { + return this.first().equals(that.first()) && this.last().equals(that.last()); + } + } + return super.equals(object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + @Override + @GwtIncompatible(value="serialization") + Object writeReplace() { + return new SerializedForm(this.range, this.domain); + } + + @GwtIncompatible(value="serialization") + private static final class SerializedForm + implements Serializable { + final Range range; + final DiscreteDomain domain; + + private SerializedForm(Range range, DiscreteDomain domain) { + this.range = range; + this.domain = domain; + } + + private Object readResolve() { + return new RegularContiguousSet(this.range, this.domain); + } + } +} diff --git a/src/com/google/common/collect/RegularImmutableAsList.java b/src/com/google/common/collect/RegularImmutableAsList.java new file mode 100644 index 0000000..8465999 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableAsList.java @@ -0,0 +1,52 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.UnmodifiableListIterator; + +@GwtCompatible(emulated=true) +class RegularImmutableAsList +extends ImmutableAsList { + private final ImmutableCollection delegate; + private final ImmutableList delegateList; + + RegularImmutableAsList(ImmutableCollection delegate, ImmutableList delegateList) { + this.delegate = delegate; + this.delegateList = delegateList; + } + + RegularImmutableAsList(ImmutableCollection delegate, Object[] array) { + this(delegate, ImmutableList.asImmutableList(array)); + } + + @Override + ImmutableCollection delegateCollection() { + return this.delegate; + } + + ImmutableList delegateList() { + return this.delegateList; + } + + @Override + public UnmodifiableListIterator listIterator(int index) { + return this.delegateList.listIterator(index); + } + + @Override + @GwtIncompatible(value="not present in emulated superclass") + int copyIntoArray(Object[] dst, int offset) { + return this.delegateList.copyIntoArray(dst, offset); + } + + @Override + public E get(int index) { + return this.delegateList.get(index); + } +} diff --git a/src/com/google/common/collect/RegularImmutableBiMap.java b/src/com/google/common/collect/RegularImmutableBiMap.java new file mode 100644 index 0000000..fe77a79 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableBiMap.java @@ -0,0 +1,308 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMapEntry; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.RegularImmutableAsList; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +class RegularImmutableBiMap +extends ImmutableBiMap { + static final double MAX_LOAD_FACTOR = 1.2; + private final transient ImmutableMapEntry[] keyTable; + private final transient ImmutableMapEntry[] valueTable; + private final transient ImmutableMapEntry[] entries; + private final transient int mask; + private final transient int hashCode; + private transient ImmutableBiMap inverse; + + RegularImmutableBiMap(ImmutableMapEntry.TerminalEntry ... entriesToAdd) { + this(entriesToAdd.length, entriesToAdd); + } + + RegularImmutableBiMap(int n, ImmutableMapEntry.TerminalEntry[] entriesToAdd) { + int tableSize = Hashing.closedTableSize(n, 1.2); + this.mask = tableSize - 1; + ImmutableMapEntry[] keyTable = RegularImmutableBiMap.createEntryArray(tableSize); + ImmutableMapEntry[] valueTable = RegularImmutableBiMap.createEntryArray(tableSize); + ImmutableMapEntry[] entries = RegularImmutableBiMap.createEntryArray(n); + int hashCode = 0; + for (int i = 0; i < n; ++i) { + ImmutableMapEntry nextInValueBucket; + ImmutableMapEntry nextInKeyBucket; + ImmutableMapEntry.TerminalEntry entry = entriesToAdd[i]; + Object key = entry.getKey(); + Object value = entry.getValue(); + int keyHash = key.hashCode(); + int valueHash = value.hashCode(); + int keyBucket = Hashing.smear(keyHash) & this.mask; + int valueBucket = Hashing.smear(valueHash) & this.mask; + for (ImmutableMapEntry keyEntry = nextInKeyBucket = keyTable[keyBucket]; keyEntry != null; keyEntry = keyEntry.getNextInKeyBucket()) { + RegularImmutableBiMap.checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry); + } + for (ImmutableMapEntry valueEntry = nextInValueBucket = valueTable[valueBucket]; valueEntry != null; valueEntry = valueEntry.getNextInValueBucket()) { + RegularImmutableBiMap.checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry); + } + ImmutableMapEntry newEntry = nextInKeyBucket == null && nextInValueBucket == null ? entry : new NonTerminalBiMapEntry(entry, nextInKeyBucket, nextInValueBucket); + keyTable[keyBucket] = newEntry; + valueTable[valueBucket] = newEntry; + entries[i] = newEntry; + hashCode += keyHash ^ valueHash; + } + this.keyTable = keyTable; + this.valueTable = valueTable; + this.entries = entries; + this.hashCode = hashCode; + } + + RegularImmutableBiMap(Map.Entry[] entriesToAdd) { + int n = entriesToAdd.length; + int tableSize = Hashing.closedTableSize(n, 1.2); + this.mask = tableSize - 1; + ImmutableMapEntry[] keyTable = RegularImmutableBiMap.createEntryArray(tableSize); + ImmutableMapEntry[] valueTable = RegularImmutableBiMap.createEntryArray(tableSize); + ImmutableMapEntry[] entries = RegularImmutableBiMap.createEntryArray(n); + int hashCode = 0; + for (int i = 0; i < n; ++i) { + ImmutableMapEntry nextInValueBucket; + ImmutableMapEntry nextInKeyBucket; + Map.Entry entry = entriesToAdd[i]; + Object key = entry.getKey(); + Object value = entry.getValue(); + CollectPreconditions.checkEntryNotNull(key, value); + int keyHash = key.hashCode(); + int valueHash = value.hashCode(); + int keyBucket = Hashing.smear(keyHash) & this.mask; + int valueBucket = Hashing.smear(valueHash) & this.mask; + for (ImmutableMapEntry keyEntry = nextInKeyBucket = keyTable[keyBucket]; keyEntry != null; keyEntry = keyEntry.getNextInKeyBucket()) { + RegularImmutableBiMap.checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry); + } + for (ImmutableMapEntry valueEntry = nextInValueBucket = valueTable[valueBucket]; valueEntry != null; valueEntry = valueEntry.getNextInValueBucket()) { + RegularImmutableBiMap.checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry); + } + ImmutableMapEntry newEntry = nextInKeyBucket == null && nextInValueBucket == null ? new ImmutableMapEntry.TerminalEntry(key, value) : new NonTerminalBiMapEntry(key, value, nextInKeyBucket, nextInValueBucket); + keyTable[keyBucket] = newEntry; + valueTable[valueBucket] = newEntry; + entries[i] = newEntry; + hashCode += keyHash ^ valueHash; + } + this.keyTable = keyTable; + this.valueTable = valueTable; + this.entries = entries; + this.hashCode = hashCode; + } + + private static ImmutableMapEntry[] createEntryArray(int length) { + return new ImmutableMapEntry[length]; + } + + @Override + @Nullable + public V get(@Nullable Object key) { + if (key == null) { + return null; + } + int bucket = Hashing.smear(key.hashCode()) & this.mask; + for (ImmutableMapEntry entry = this.keyTable[bucket]; entry != null; entry = entry.getNextInKeyBucket()) { + if (!key.equals(entry.getKey())) continue; + return entry.getValue(); + } + return null; + } + + @Override + ImmutableSet> createEntrySet() { + return new ImmutableMapEntrySet(){ + + @Override + ImmutableMap map() { + return RegularImmutableBiMap.this; + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new RegularImmutableAsList(this, RegularImmutableBiMap.this.entries); + } + + @Override + boolean isHashCodeFast() { + return true; + } + + @Override + public int hashCode() { + return RegularImmutableBiMap.this.hashCode; + } + }; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public int size() { + return this.entries.length; + } + + @Override + public ImmutableBiMap inverse() { + Inverse result = this.inverse; + return result == null ? (this.inverse = new Inverse()) : result; + } + + private static class InverseSerializedForm + implements Serializable { + private final ImmutableBiMap forward; + private static final long serialVersionUID = 1L; + + InverseSerializedForm(ImmutableBiMap forward) { + this.forward = forward; + } + + Object readResolve() { + return this.forward.inverse(); + } + } + + private final class Inverse + extends ImmutableBiMap { + private Inverse() { + } + + @Override + public int size() { + return this.inverse().size(); + } + + @Override + public ImmutableBiMap inverse() { + return RegularImmutableBiMap.this; + } + + @Override + public K get(@Nullable Object value) { + if (value == null) { + return null; + } + int bucket = Hashing.smear(value.hashCode()) & RegularImmutableBiMap.this.mask; + for (ImmutableMapEntry entry = RegularImmutableBiMap.this.valueTable[bucket]; entry != null; entry = entry.getNextInValueBucket()) { + if (!value.equals(entry.getValue())) continue; + return entry.getKey(); + } + return null; + } + + @Override + ImmutableSet> createEntrySet() { + return new InverseEntrySet(); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + Object writeReplace() { + return new InverseSerializedForm(RegularImmutableBiMap.this); + } + + final class InverseEntrySet + extends ImmutableMapEntrySet { + InverseEntrySet() { + } + + @Override + ImmutableMap map() { + return Inverse.this; + } + + @Override + boolean isHashCodeFast() { + return true; + } + + @Override + public int hashCode() { + return RegularImmutableBiMap.this.hashCode; + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new ImmutableAsList>(){ + + @Override + public Map.Entry get(int index) { + ImmutableMapEntry entry = RegularImmutableBiMap.this.entries[index]; + return Maps.immutableEntry(entry.getValue(), entry.getKey()); + } + + @Override + ImmutableCollection> delegateCollection() { + return InverseEntrySet.this; + } + }; + } + } + } + + private static final class NonTerminalBiMapEntry + extends ImmutableMapEntry { + @Nullable + private final ImmutableMapEntry nextInKeyBucket; + @Nullable + private final ImmutableMapEntry nextInValueBucket; + + NonTerminalBiMapEntry(K key, V value, @Nullable ImmutableMapEntry nextInKeyBucket, @Nullable ImmutableMapEntry nextInValueBucket) { + super(key, value); + this.nextInKeyBucket = nextInKeyBucket; + this.nextInValueBucket = nextInValueBucket; + } + + NonTerminalBiMapEntry(ImmutableMapEntry contents, @Nullable ImmutableMapEntry nextInKeyBucket, @Nullable ImmutableMapEntry nextInValueBucket) { + super(contents); + this.nextInKeyBucket = nextInKeyBucket; + this.nextInValueBucket = nextInValueBucket; + } + + @Override + @Nullable + ImmutableMapEntry getNextInKeyBucket() { + return this.nextInKeyBucket; + } + + @Override + @Nullable + ImmutableMapEntry getNextInValueBucket() { + return this.nextInValueBucket; + } + } +} diff --git a/src/com/google/common/collect/RegularImmutableList.java b/src/com/google/common/collect/RegularImmutableList.java new file mode 100644 index 0000000..a8d8aef --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableList.java @@ -0,0 +1,85 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableListIterator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +class RegularImmutableList +extends ImmutableList { + private final transient int offset; + private final transient int size; + private final transient Object[] array; + + RegularImmutableList(Object[] array, int offset, int size) { + this.offset = offset; + this.size = size; + this.array = array; + } + + RegularImmutableList(Object[] array) { + this(array, 0, array.length); + } + + @Override + public int size() { + return this.size; + } + + @Override + boolean isPartialView() { + return this.size != this.array.length; + } + + @Override + int copyIntoArray(Object[] dst, int dstOff) { + System.arraycopy(this.array, this.offset, dst, dstOff, this.size); + return dstOff + this.size; + } + + @Override + public E get(int index) { + Preconditions.checkElementIndex(index, this.size); + return (E)this.array[index + this.offset]; + } + + @Override + public int indexOf(@Nullable Object object) { + if (object == null) { + return -1; + } + for (int i = 0; i < this.size; ++i) { + if (!this.array[this.offset + i].equals(object)) continue; + return i; + } + return -1; + } + + @Override + public int lastIndexOf(@Nullable Object object) { + if (object == null) { + return -1; + } + for (int i = this.size - 1; i >= 0; --i) { + if (!this.array[this.offset + i].equals(object)) continue; + return i; + } + return -1; + } + + @Override + ImmutableList subListUnchecked(int fromIndex, int toIndex) { + return new RegularImmutableList(this.array, this.offset + fromIndex, toIndex - fromIndex); + } + + @Override + public UnmodifiableListIterator listIterator(int index) { + return Iterators.forArray(this.array, this.offset, this.size, index); + } +} diff --git a/src/com/google/common/collect/RegularImmutableMap.java b/src/com/google/common/collect/RegularImmutableMap.java new file mode 100644 index 0000000..af5b7d4 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableMap.java @@ -0,0 +1,155 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMapEntry; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.RegularImmutableAsList; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableMap +extends ImmutableMap { + private final transient ImmutableMapEntry[] entries; + private final transient ImmutableMapEntry[] table; + private final transient int mask; + private static final double MAX_LOAD_FACTOR = 1.2; + private static final long serialVersionUID = 0L; + + RegularImmutableMap(ImmutableMapEntry.TerminalEntry ... theEntries) { + this(theEntries.length, theEntries); + } + + RegularImmutableMap(int size, ImmutableMapEntry.TerminalEntry[] theEntries) { + this.entries = this.createEntryArray(size); + int tableSize = Hashing.closedTableSize(size, 1.2); + this.table = this.createEntryArray(tableSize); + this.mask = tableSize - 1; + for (int entryIndex = 0; entryIndex < size; ++entryIndex) { + ImmutableMapEntry.TerminalEntry entry = theEntries[entryIndex]; + Object key = entry.getKey(); + int tableIndex = Hashing.smear(key.hashCode()) & this.mask; + ImmutableMapEntry existing = this.table[tableIndex]; + ImmutableMapEntry newEntry = existing == null ? entry : new NonTerminalMapEntry((ImmutableMapEntry)entry, existing); + this.table[tableIndex] = newEntry; + this.entries[entryIndex] = newEntry; + this.checkNoConflictInBucket(key, newEntry, existing); + } + } + + RegularImmutableMap(Map.Entry[] theEntries) { + int size = theEntries.length; + this.entries = this.createEntryArray(size); + int tableSize = Hashing.closedTableSize(size, 1.2); + this.table = this.createEntryArray(tableSize); + this.mask = tableSize - 1; + for (int entryIndex = 0; entryIndex < size; ++entryIndex) { + Map.Entry entry = theEntries[entryIndex]; + Object key = entry.getKey(); + Object value = entry.getValue(); + CollectPreconditions.checkEntryNotNull(key, value); + int tableIndex = Hashing.smear(key.hashCode()) & this.mask; + ImmutableMapEntry existing = this.table[tableIndex]; + ImmutableMapEntry newEntry = existing == null ? new ImmutableMapEntry.TerminalEntry(key, value) : new NonTerminalMapEntry(key, value, existing); + this.table[tableIndex] = newEntry; + this.entries[entryIndex] = newEntry; + this.checkNoConflictInBucket(key, newEntry, existing); + } + } + + private void checkNoConflictInBucket(K key, ImmutableMapEntry entry, ImmutableMapEntry bucketHead) { + while (bucketHead != null) { + RegularImmutableMap.checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead); + bucketHead = bucketHead.getNextInKeyBucket(); + } + } + + private ImmutableMapEntry[] createEntryArray(int size) { + return new ImmutableMapEntry[size]; + } + + @Override + public V get(@Nullable Object key) { + if (key == null) { + return null; + } + int index = Hashing.smear(key.hashCode()) & this.mask; + for (ImmutableMapEntry entry = this.table[index]; entry != null; entry = entry.getNextInKeyBucket()) { + Object candidateKey = entry.getKey(); + if (!key.equals(candidateKey)) continue; + return entry.getValue(); + } + return null; + } + + @Override + public int size() { + return this.entries.length; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + ImmutableSet> createEntrySet() { + return new EntrySet(); + } + + private class EntrySet + extends ImmutableMapEntrySet { + private EntrySet() { + } + + @Override + ImmutableMap map() { + return RegularImmutableMap.this; + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new RegularImmutableAsList(this, RegularImmutableMap.this.entries); + } + } + + private static final class NonTerminalMapEntry + extends ImmutableMapEntry { + private final ImmutableMapEntry nextInKeyBucket; + + NonTerminalMapEntry(K key, V value, ImmutableMapEntry nextInKeyBucket) { + super(key, value); + this.nextInKeyBucket = nextInKeyBucket; + } + + NonTerminalMapEntry(ImmutableMapEntry contents, ImmutableMapEntry nextInKeyBucket) { + super(contents); + this.nextInKeyBucket = nextInKeyBucket; + } + + @Override + ImmutableMapEntry getNextInKeyBucket() { + return this.nextInKeyBucket; + } + + @Override + @Nullable + ImmutableMapEntry getNextInValueBucket() { + return null; + } + } +} diff --git a/src/com/google/common/collect/RegularImmutableMultiset.java b/src/com/google/common/collect/RegularImmutableMultiset.java new file mode 100644 index 0000000..20f938f --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableMultiset.java @@ -0,0 +1,63 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +class RegularImmutableMultiset +extends ImmutableMultiset { + private final transient ImmutableMap map; + private final transient int size; + + RegularImmutableMultiset(ImmutableMap map, int size) { + this.map = map; + this.size = size; + } + + @Override + boolean isPartialView() { + return this.map.isPartialView(); + } + + @Override + public int count(@Nullable Object element) { + Integer value = this.map.get(element); + return value == null ? 0 : value; + } + + @Override + public int size() { + return this.size; + } + + @Override + public boolean contains(@Nullable Object element) { + return this.map.containsKey(element); + } + + @Override + public ImmutableSet elementSet() { + return this.map.keySet(); + } + + @Override + Multiset.Entry getEntry(int index) { + Map.Entry mapEntry = (Map.Entry)((ImmutableCollection)((Object)this.map.entrySet())).asList().get(index); + return Multisets.immutableEntry(mapEntry.getKey(), (Integer)mapEntry.getValue()); + } + + @Override + public int hashCode() { + return this.map.hashCode(); + } +} diff --git a/src/com/google/common/collect/RegularImmutableSet.java b/src/com/google/common/collect/RegularImmutableSet.java new file mode 100644 index 0000000..e4ebb39 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableSet.java @@ -0,0 +1,82 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Hashing; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.RegularImmutableAsList; +import com.google.common.collect.UnmodifiableIterator; + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableSet +extends ImmutableSet { + private final Object[] elements; + @VisibleForTesting + final transient Object[] table; + private final transient int mask; + private final transient int hashCode; + + RegularImmutableSet(Object[] elements, int hashCode, Object[] table, int mask) { + this.elements = elements; + this.table = table; + this.mask = mask; + this.hashCode = hashCode; + } + + @Override + public boolean contains(Object target) { + if (target == null) { + return false; + } + int i = Hashing.smear(target.hashCode()); + Object candidate; + while ((candidate = this.table[i & this.mask]) != null) { + if (candidate.equals(target)) { + return true; + } + ++i; + } + return false; + } + + @Override + public int size() { + return this.elements.length; + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.forArray(this.elements); + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + System.arraycopy(this.elements, 0, dst, offset, this.elements.length); + return offset + this.elements.length; + } + + @Override + ImmutableList createAsList() { + return new RegularImmutableAsList(this, this.elements); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + public int hashCode() { + return this.hashCode; + } + + @Override + boolean isHashCodeFast() { + return true; + } +} diff --git a/src/com/google/common/collect/RegularImmutableSortedMap.java b/src/com/google/common/collect/RegularImmutableSortedMap.java new file mode 100644 index 0000000..b89c86a --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableSortedMap.java @@ -0,0 +1,120 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMapEntrySet; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class RegularImmutableSortedMap +extends ImmutableSortedMap { + private final transient RegularImmutableSortedSet keySet; + private final transient ImmutableList valueList; + + RegularImmutableSortedMap(RegularImmutableSortedSet keySet, ImmutableList valueList) { + this.keySet = keySet; + this.valueList = valueList; + } + + RegularImmutableSortedMap(RegularImmutableSortedSet keySet, ImmutableList valueList, ImmutableSortedMap descendingMap) { + super(descendingMap); + this.keySet = keySet; + this.valueList = valueList; + } + + @Override + ImmutableSet> createEntrySet() { + return new EntrySet(); + } + + @Override + public ImmutableSortedSet keySet() { + return this.keySet; + } + + @Override + public ImmutableCollection values() { + return this.valueList; + } + + @Override + public V get(@Nullable Object key) { + int index = this.keySet.indexOf(key); + return index == -1 ? null : (V)this.valueList.get(index); + } + + private ImmutableSortedMap getSubMap(int fromIndex, int toIndex) { + if (fromIndex == 0 && toIndex == this.size()) { + return this; + } + if (fromIndex == toIndex) { + return RegularImmutableSortedMap.emptyMap(this.comparator()); + } + return RegularImmutableSortedMap.from(this.keySet.getSubSet(fromIndex, toIndex), this.valueList.subList(fromIndex, toIndex)); + } + + @Override + public ImmutableSortedMap headMap(K toKey, boolean inclusive) { + return this.getSubMap(0, this.keySet.headIndex(Preconditions.checkNotNull(toKey), inclusive)); + } + + @Override + public ImmutableSortedMap tailMap(K fromKey, boolean inclusive) { + return this.getSubMap(this.keySet.tailIndex(Preconditions.checkNotNull(fromKey), inclusive), this.size()); + } + + @Override + ImmutableSortedMap createDescendingMap() { + return new RegularImmutableSortedMap((RegularImmutableSortedSet)this.keySet.descendingSet(), this.valueList.reverse(), this); + } + + private class EntrySet + extends ImmutableMapEntrySet { + private EntrySet() { + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new ImmutableAsList>(){ + private final ImmutableList keyList; + { + this.keyList = ((ImmutableCollection)((Object)RegularImmutableSortedMap.this.keySet())).asList(); + } + + @Override + public Map.Entry get(int index) { + return Maps.immutableEntry(this.keyList.get(index), RegularImmutableSortedMap.this.valueList.get(index)); + } + + @Override + ImmutableCollection> delegateCollection() { + return EntrySet.this; + } + }; + } + + @Override + ImmutableMap map() { + return RegularImmutableSortedMap.this; + } + } +} diff --git a/src/com/google/common/collect/RegularImmutableSortedMultiset.java b/src/com/google/common/collect/RegularImmutableSortedMultiset.java new file mode 100644 index 0000000..3ee3454 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableSortedMultiset.java @@ -0,0 +1,90 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import com.google.common.collect.BoundType; +import com.google.common.collect.ImmutableSortedMultiset; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.RegularImmutableSortedSet; +import com.google.common.primitives.Ints; +import javax.annotation.Nullable; + +final class RegularImmutableSortedMultiset +extends ImmutableSortedMultiset { + private final transient RegularImmutableSortedSet elementSet; + private final transient int[] counts; + private final transient long[] cumulativeCounts; + private final transient int offset; + private final transient int length; + + RegularImmutableSortedMultiset(RegularImmutableSortedSet elementSet, int[] counts, long[] cumulativeCounts, int offset, int length) { + this.elementSet = elementSet; + this.counts = counts; + this.cumulativeCounts = cumulativeCounts; + this.offset = offset; + this.length = length; + } + + @Override + Multiset.Entry getEntry(int index) { + return Multisets.immutableEntry(this.elementSet.asList().get(index), this.counts[this.offset + index]); + } + + @Override + public Multiset.Entry firstEntry() { + return this.getEntry(0); + } + + @Override + public Multiset.Entry lastEntry() { + return this.getEntry(this.length - 1); + } + + @Override + public int count(@Nullable Object element) { + int index = this.elementSet.indexOf(element); + return index == -1 ? 0 : this.counts[index + this.offset]; + } + + @Override + public int size() { + long size = this.cumulativeCounts[this.offset + this.length] - this.cumulativeCounts[this.offset]; + return Ints.saturatedCast(size); + } + + @Override + public ImmutableSortedSet elementSet() { + return this.elementSet; + } + + @Override + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) { + return this.getSubMultiset(0, this.elementSet.headIndex(upperBound, Preconditions.checkNotNull(boundType) == BoundType.CLOSED)); + } + + @Override + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) { + return this.getSubMultiset(this.elementSet.tailIndex(lowerBound, Preconditions.checkNotNull(boundType) == BoundType.CLOSED), this.length); + } + + ImmutableSortedMultiset getSubMultiset(int from, int to) { + Preconditions.checkPositionIndexes(from, to, this.length); + if (from == to) { + return RegularImmutableSortedMultiset.emptyMultiset(this.comparator()); + } + if (from == 0 && to == this.length) { + return this; + } + RegularImmutableSortedSet subElementSet = (RegularImmutableSortedSet)this.elementSet.getSubSet(from, to); + return new RegularImmutableSortedMultiset(subElementSet, this.counts, this.cumulativeCounts, this.offset + from, to - from); + } + + @Override + boolean isPartialView() { + return this.offset > 0 || this.length < this.counts.length; + } +} diff --git a/src/com/google/common/collect/RegularImmutableSortedSet.java b/src/com/google/common/collect/RegularImmutableSortedSet.java new file mode 100644 index 0000000..acb0662 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableSortedSet.java @@ -0,0 +1,248 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedAsList; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.SortedIterables; +import com.google.common.collect.SortedLists; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableSortedSet +extends ImmutableSortedSet { + private final transient ImmutableList elements; + + RegularImmutableSortedSet(ImmutableList elements, Comparator comparator) { + super(comparator); + this.elements = elements; + Preconditions.checkArgument(!elements.isEmpty()); + } + + @Override + public UnmodifiableIterator iterator() { + return this.elements.iterator(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public UnmodifiableIterator descendingIterator() { + return this.elements.reverse().iterator(); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public int size() { + return this.elements.size(); + } + + @Override + public boolean contains(Object o) { + try { + return o != null && this.unsafeBinarySearch(o) >= 0; + } + catch (ClassCastException e) { + return false; + } + } + + @Override + public boolean containsAll(Collection targets) { + if (targets instanceof Multiset) { + targets = ((Multiset)targets).elementSet(); + } + if (!SortedIterables.hasSameComparator(this.comparator(), targets) || targets.size() <= 1) { + return super.containsAll(targets); + } + PeekingIterator thisIterator = Iterators.peekingIterator(this.iterator()); + Iterator thatIterator = targets.iterator(); + Object target = thatIterator.next(); + try { + while (thisIterator.hasNext()) { + int cmp = this.unsafeCompare(thisIterator.peek(), target); + if (cmp < 0) { + thisIterator.next(); + continue; + } + if (cmp == 0) { + if (!thatIterator.hasNext()) { + return true; + } + target = thatIterator.next(); + continue; + } + if (cmp <= 0) continue; + return false; + } + } + catch (NullPointerException e) { + return false; + } + catch (ClassCastException e) { + return false; + } + return false; + } + + private int unsafeBinarySearch(Object key) throws ClassCastException { + return Collections.binarySearch(this.elements, key, this.unsafeComparator()); + } + + @Override + boolean isPartialView() { + return this.elements.isPartialView(); + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + return this.elements.copyIntoArray(dst, offset); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (!(object instanceof Set)) { + return false; + } + Set that = (Set)object; + if (this.size() != that.size()) { + return false; + } + if (SortedIterables.hasSameComparator(this.comparator, that)) { + Iterator otherIterator = that.iterator(); + try { + for (Object element : this) { + Object otherElement = otherIterator.next(); + if (otherElement != null && this.unsafeCompare(element, otherElement) == 0) continue; + return false; + } + return true; + } + catch (ClassCastException e) { + return false; + } + catch (NoSuchElementException e) { + return false; + } + } + return this.containsAll(that); + } + + @Override + public E first() { + return this.elements.get(0); + } + + @Override + public E last() { + return this.elements.get(this.size() - 1); + } + + @Override + public E lower(E element) { + int index = this.headIndex(element, false) - 1; + return index == -1 ? null : (E)this.elements.get(index); + } + + @Override + public E floor(E element) { + int index = this.headIndex(element, true) - 1; + return index == -1 ? null : (E)this.elements.get(index); + } + + @Override + public E ceiling(E element) { + int index = this.tailIndex(element, true); + return index == this.size() ? null : (E)this.elements.get(index); + } + + @Override + public E higher(E element) { + int index = this.tailIndex(element, false); + return index == this.size() ? null : (E)this.elements.get(index); + } + + @Override + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) { + return this.getSubSet(0, this.headIndex(toElement, inclusive)); + } + + int headIndex(E toElement, boolean inclusive) { + return SortedLists.binarySearch(this.elements, Preconditions.checkNotNull(toElement), this.comparator(), inclusive ? SortedLists.KeyPresentBehavior.FIRST_AFTER : SortedLists.KeyPresentBehavior.FIRST_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + + @Override + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return this.tailSetImpl(fromElement, fromInclusive).headSetImpl(toElement, toInclusive); + } + + @Override + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) { + return this.getSubSet(this.tailIndex(fromElement, inclusive), this.size()); + } + + int tailIndex(E fromElement, boolean inclusive) { + return SortedLists.binarySearch(this.elements, Preconditions.checkNotNull(fromElement), this.comparator(), inclusive ? SortedLists.KeyPresentBehavior.FIRST_PRESENT : SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + + Comparator unsafeComparator() { + return this.comparator; + } + + ImmutableSortedSet getSubSet(int newFromIndex, int newToIndex) { + if (newFromIndex == 0 && newToIndex == this.size()) { + return this; + } + if (newFromIndex < newToIndex) { + return new RegularImmutableSortedSet(this.elements.subList(newFromIndex, newToIndex), this.comparator); + } + return RegularImmutableSortedSet.emptySet(this.comparator); + } + + @Override + int indexOf(@Nullable Object target) { + int position; + if (target == null) { + return -1; + } + try { + position = SortedLists.binarySearch(this.elements, target, this.unsafeComparator(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX); + } + catch (ClassCastException e) { + return -1; + } + return position >= 0 ? position : -1; + } + + @Override + ImmutableList createAsList() { + return new ImmutableSortedAsList(this, this.elements); + } + + @Override + ImmutableSortedSet createDescendingSet() { + return new RegularImmutableSortedSet(this.elements.reverse(), Ordering.from(this.comparator).reverse()); + } +} diff --git a/src/com/google/common/collect/RegularImmutableTable.java b/src/com/google/common/collect/RegularImmutableTable.java new file mode 100644 index 0000000..07f32f5 --- /dev/null +++ b/src/com/google/common/collect/RegularImmutableTable.java @@ -0,0 +1,162 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.DenseImmutableTable; +import com.google.common.collect.ImmutableAsList; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Lists; +import com.google.common.collect.SparseImmutableTable; +import com.google.common.collect.Table; +import com.google.common.collect.UnmodifiableIterator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible +abstract class RegularImmutableTable +extends ImmutableTable { + RegularImmutableTable() { + } + + abstract Table.Cell getCell(int var1); + + @Override + final ImmutableSet> createCellSet() { + return this.isEmpty() ? ImmutableSet.of() : new CellSet(); + } + + abstract V getValue(int var1); + + @Override + final ImmutableCollection createValues() { + return this.isEmpty() ? ImmutableList.of() : new Values(); + } + + static RegularImmutableTable forCells(List> cells, final @Nullable Comparator rowComparator, final @Nullable Comparator columnComparator) { + Preconditions.checkNotNull(cells); + if (rowComparator != null || columnComparator != null) { + Comparator comparator = new Comparator>(){ + + @Override + public int compare(Table.Cell cell1, Table.Cell cell2) { + int rowCompare; + int n = rowCompare = rowComparator == null ? 0 : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey()); + if (rowCompare != 0) { + return rowCompare; + } + return columnComparator == null ? 0 : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey()); + } + }; + Collections.sort(cells, comparator); + } + return RegularImmutableTable.forCellsInternal(cells, rowComparator, columnComparator); + } + + static RegularImmutableTable forCells(Iterable> cells) { + return RegularImmutableTable.forCellsInternal(cells, null, null); + } + + /* + * WARNING - void declaration + */ + private static final RegularImmutableTable forCellsInternal(Iterable> cells, @Nullable Comparator rowComparator, @Nullable Comparator columnComparator) { + void var7_12; + ImmutableSet.Builder rowSpaceBuilder = ImmutableSet.builder(); + ImmutableSet.Builder columnSpaceBuilder = ImmutableSet.builder(); + ImmutableList> cellList = ImmutableList.copyOf(cells); + for (Table.Cell cell : cellList) { + rowSpaceBuilder.add(cell.getRowKey()); + columnSpaceBuilder.add(cell.getColumnKey()); + } + ImmutableSet rowSpace = rowSpaceBuilder.build(); + if (rowComparator != null) { + ArrayList arrayList = Lists.newArrayList(rowSpace); + Collections.sort(arrayList, rowComparator); + rowSpace = ImmutableSet.copyOf(arrayList); + } + ImmutableCollection immutableCollection = columnSpaceBuilder.build(); + if (columnComparator != null) { + ArrayList columnList = Lists.newArrayList(immutableCollection); + Collections.sort(columnList, columnComparator); + ImmutableSet immutableSet = ImmutableSet.copyOf(columnList); + } + return (long)cellList.size() > (long)rowSpace.size() * (long)var7_12.size() / 2L ? new DenseImmutableTable(cellList, rowSpace, var7_12) : new SparseImmutableTable(cellList, rowSpace, var7_12); + } + + private final class Values + extends ImmutableList { + private Values() { + } + + @Override + public int size() { + return RegularImmutableTable.this.size(); + } + + @Override + public V get(int index) { + return RegularImmutableTable.this.getValue(index); + } + + @Override + boolean isPartialView() { + return true; + } + } + + private final class CellSet + extends ImmutableSet> { + private CellSet() { + } + + @Override + public int size() { + return RegularImmutableTable.this.size(); + } + + @Override + public UnmodifiableIterator> iterator() { + return this.asList().iterator(); + } + + @Override + ImmutableList> createAsList() { + return new ImmutableAsList>(){ + + @Override + public Table.Cell get(int index) { + return RegularImmutableTable.this.getCell(index); + } + + @Override + ImmutableCollection> delegateCollection() { + return CellSet.this; + } + }; + } + + @Override + public boolean contains(@Nullable Object object) { + if (object instanceof Table.Cell) { + Table.Cell cell = (Table.Cell)object; + Object value = RegularImmutableTable.this.get(cell.getRowKey(), cell.getColumnKey()); + return value != null && value.equals(cell.getValue()); + } + return false; + } + + @Override + boolean isPartialView() { + return false; + } + } +} diff --git a/src/com/google/common/collect/ReverseNaturalOrdering.java b/src/com/google/common/collect/ReverseNaturalOrdering.java new file mode 100644 index 0000000..c477d97 --- /dev/null +++ b/src/com/google/common/collect/ReverseNaturalOrdering.java @@ -0,0 +1,84 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.NaturalOrdering; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Iterator; + +@GwtCompatible(serializable=true) +final class ReverseNaturalOrdering +extends Ordering +implements Serializable { + static final ReverseNaturalOrdering INSTANCE = new ReverseNaturalOrdering(); + private static final long serialVersionUID = 0L; + + @Override + public int compare(Comparable left, Comparable right) { + Preconditions.checkNotNull(left); + if (left == right) { + return 0; + } + return right.compareTo(left); + } + + @Override + public Ordering reverse() { + return Ordering.natural(); + } + + @Override + public E min(E a, E b) { + return NaturalOrdering.INSTANCE.max(a, b); + } + + @Override + public E min(E a, E b, E c, E ... rest) { + return NaturalOrdering.INSTANCE.max(a, b, c, rest); + } + + @Override + public E min(Iterator iterator) { + return (E)((Comparable)NaturalOrdering.INSTANCE.max(iterator)); + } + + @Override + public E min(Iterable iterable) { + return (E)((Comparable)NaturalOrdering.INSTANCE.max(iterable)); + } + + @Override + public E max(E a, E b) { + return NaturalOrdering.INSTANCE.min(a, b); + } + + @Override + public E max(E a, E b, E c, E ... rest) { + return NaturalOrdering.INSTANCE.min(a, b, c, rest); + } + + @Override + public E max(Iterator iterator) { + return (E)((Comparable)NaturalOrdering.INSTANCE.min(iterator)); + } + + @Override + public E max(Iterable iterable) { + return (E)((Comparable)NaturalOrdering.INSTANCE.min(iterable)); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "Ordering.natural().reverse()"; + } + + private ReverseNaturalOrdering() { + } +} diff --git a/src/com/google/common/collect/ReverseOrdering.java b/src/com/google/common/collect/ReverseOrdering.java new file mode 100644 index 0000000..19e6612 --- /dev/null +++ b/src/com/google/common/collect/ReverseOrdering.java @@ -0,0 +1,94 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Ordering; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +final class ReverseOrdering +extends Ordering +implements Serializable { + final Ordering forwardOrder; + private static final long serialVersionUID = 0L; + + ReverseOrdering(Ordering forwardOrder) { + this.forwardOrder = Preconditions.checkNotNull(forwardOrder); + } + + @Override + public int compare(T a, T b) { + return this.forwardOrder.compare(b, a); + } + + @Override + public Ordering reverse() { + return this.forwardOrder; + } + + @Override + public E min(E a, E b) { + return this.forwardOrder.max(a, b); + } + + @Override + public E min(E a, E b, E c, E ... rest) { + return this.forwardOrder.max(a, b, c, rest); + } + + @Override + public E min(Iterator iterator) { + return this.forwardOrder.max(iterator); + } + + @Override + public E min(Iterable iterable) { + return this.forwardOrder.max(iterable); + } + + @Override + public E max(E a, E b) { + return this.forwardOrder.min(a, b); + } + + @Override + public E max(E a, E b, E c, E ... rest) { + return this.forwardOrder.min(a, b, c, rest); + } + + @Override + public E max(Iterator iterator) { + return this.forwardOrder.min(iterator); + } + + @Override + public E max(Iterable iterable) { + return this.forwardOrder.min(iterable); + } + + public int hashCode() { + return -this.forwardOrder.hashCode(); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof ReverseOrdering) { + ReverseOrdering that = (ReverseOrdering)object; + return this.forwardOrder.equals(that.forwardOrder); + } + return false; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.forwardOrder)); + return new StringBuilder(10 + string.length()).append(string).append(".reverse()").toString(); + } +} diff --git a/src/com/google/common/collect/RowSortedTable.java b/src/com/google/common/collect/RowSortedTable.java new file mode 100644 index 0000000..2df832d --- /dev/null +++ b/src/com/google/common/collect/RowSortedTable.java @@ -0,0 +1,22 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Table; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + +@GwtCompatible +@Beta +public interface RowSortedTable +extends Table { + @Override + public SortedSet rowKeySet(); + + @Override + public SortedMap> rowMap(); +} diff --git a/src/com/google/common/collect/Serialization.java b/src/com/google/common/collect/Serialization.java new file mode 100644 index 0000000..62f90f2 --- /dev/null +++ b/src/com/google/common/collect/Serialization.java @@ -0,0 +1,130 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Map; + +final class Serialization { + private Serialization() { + } + + static int readCount(ObjectInputStream stream) throws IOException { + return stream.readInt(); + } + + static void writeMap(Map map, ObjectOutputStream stream) throws IOException { + stream.writeInt(map.size()); + for (Map.Entry entry : map.entrySet()) { + stream.writeObject(entry.getKey()); + stream.writeObject(entry.getValue()); + } + } + + static void populateMap(Map map, ObjectInputStream stream) throws IOException, ClassNotFoundException { + int size = stream.readInt(); + Serialization.populateMap(map, stream, size); + } + + static void populateMap(Map map, ObjectInputStream stream, int size) throws IOException, ClassNotFoundException { + for (int i = 0; i < size; ++i) { + Object key = stream.readObject(); + Object value = stream.readObject(); + map.put(key, value); + } + } + + static void writeMultiset(Multiset multiset, ObjectOutputStream stream) throws IOException { + int entryCount = multiset.entrySet().size(); + stream.writeInt(entryCount); + for (Multiset.Entry entry : multiset.entrySet()) { + stream.writeObject(entry.getElement()); + stream.writeInt(entry.getCount()); + } + } + + static void populateMultiset(Multiset multiset, ObjectInputStream stream) throws IOException, ClassNotFoundException { + int distinctElements = stream.readInt(); + Serialization.populateMultiset(multiset, stream, distinctElements); + } + + static void populateMultiset(Multiset multiset, ObjectInputStream stream, int distinctElements) throws IOException, ClassNotFoundException { + for (int i = 0; i < distinctElements; ++i) { + Object element = stream.readObject(); + int count = stream.readInt(); + multiset.add(element, count); + } + } + + static void writeMultimap(Multimap multimap, ObjectOutputStream stream) throws IOException { + stream.writeInt(multimap.asMap().size()); + for (Map.Entry> entry : multimap.asMap().entrySet()) { + stream.writeObject(entry.getKey()); + stream.writeInt(entry.getValue().size()); + for (V value : entry.getValue()) { + stream.writeObject(value); + } + } + } + + static void populateMultimap(Multimap multimap, ObjectInputStream stream) throws IOException, ClassNotFoundException { + int distinctKeys = stream.readInt(); + Serialization.populateMultimap(multimap, stream, distinctKeys); + } + + static void populateMultimap(Multimap multimap, ObjectInputStream stream, int distinctKeys) throws IOException, ClassNotFoundException { + for (int i = 0; i < distinctKeys; ++i) { + Object key = stream.readObject(); + Collection values = multimap.get(key); + int valueCount = stream.readInt(); + for (int j = 0; j < valueCount; ++j) { + Object value = stream.readObject(); + values.add(value); + } + } + } + + static FieldSetter getFieldSetter(Class clazz, String fieldName) { + try { + Field field = clazz.getDeclaredField(fieldName); + return new FieldSetter(field); + } + catch (NoSuchFieldException e) { + throw new AssertionError((Object)e); + } + } + + static final class FieldSetter { + private final Field field; + + private FieldSetter(Field field) { + this.field = field; + field.setAccessible(true); + } + + void set(T instance, Object value) { + try { + this.field.set(instance, value); + } + catch (IllegalAccessException impossible) { + throw new AssertionError((Object)impossible); + } + } + + void set(T instance, int value) { + try { + this.field.set(instance, value); + } + catch (IllegalAccessException impossible) { + throw new AssertionError((Object)impossible); + } + } + } +} diff --git a/src/com/google/common/collect/SetMultimap.java b/src/com/google/common/collect/SetMultimap.java new file mode 100644 index 0000000..d802923 --- /dev/null +++ b/src/com/google/common/collect/SetMultimap.java @@ -0,0 +1,33 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public interface SetMultimap +extends Multimap { + @Override + public Set get(@Nullable K var1); + + @Override + public Set removeAll(@Nullable Object var1); + + @Override + public Set replaceValues(K var1, Iterable var2); + + @Override + public Set> entries(); + + @Override + public Map> asMap(); + + @Override + public boolean equals(@Nullable Object var1); +} diff --git a/src/com/google/common/collect/Sets.java b/src/com/google/common/collect/Sets.java new file mode 100644 index 0000000..47d55d3 --- /dev/null +++ b/src/com/google/common/collect/Sets.java @@ -0,0 +1,972 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIndexedListIterator; +import com.google.common.collect.CartesianList; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingNavigableSet; +import com.google.common.collect.ForwardingSortedSet; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableEnumSet; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.Platform; +import com.google.common.collect.Synchronized; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Sets { + private Sets() { + } + + @GwtCompatible(serializable=true) + public static > ImmutableSet immutableEnumSet(E anElement, E ... otherElements) { + return ImmutableEnumSet.asImmutable(EnumSet.of(anElement, otherElements)); + } + + @GwtCompatible(serializable=true) + public static > ImmutableSet immutableEnumSet(Iterable elements) { + if (elements instanceof ImmutableEnumSet) { + return (ImmutableEnumSet)elements; + } + if (elements instanceof Collection) { + Collection collection = (Collection)elements; + if (collection.isEmpty()) { + return ImmutableSet.of(); + } + return ImmutableEnumSet.asImmutable(EnumSet.copyOf(collection)); + } + Iterator itr = elements.iterator(); + if (itr.hasNext()) { + EnumSet enumSet = EnumSet.of((Enum)itr.next()); + Iterators.addAll(enumSet, itr); + return ImmutableEnumSet.asImmutable(enumSet); + } + return ImmutableSet.of(); + } + + public static > EnumSet newEnumSet(Iterable iterable, Class elementType) { + EnumSet set = EnumSet.noneOf(elementType); + Iterables.addAll(set, iterable); + return set; + } + + public static HashSet newHashSet() { + return new HashSet(); + } + + public static HashSet newHashSet(E ... elements) { + HashSet set = Sets.newHashSetWithExpectedSize(elements.length); + Collections.addAll(set, elements); + return set; + } + + public static HashSet newHashSetWithExpectedSize(int expectedSize) { + return new HashSet(Maps.capacity(expectedSize)); + } + + public static HashSet newHashSet(Iterable elements) { + return elements instanceof Collection ? new HashSet(Collections2.cast(elements)) : Sets.newHashSet(elements.iterator()); + } + + public static HashSet newHashSet(Iterator elements) { + HashSet set = Sets.newHashSet(); + Iterators.addAll(set, elements); + return set; + } + + public static Set newConcurrentHashSet() { + return Sets.newSetFromMap(new ConcurrentHashMap()); + } + + public static Set newConcurrentHashSet(Iterable elements) { + Set set = Sets.newConcurrentHashSet(); + Iterables.addAll(set, elements); + return set; + } + + public static LinkedHashSet newLinkedHashSet() { + return new LinkedHashSet(); + } + + public static LinkedHashSet newLinkedHashSetWithExpectedSize(int expectedSize) { + return new LinkedHashSet(Maps.capacity(expectedSize)); + } + + public static LinkedHashSet newLinkedHashSet(Iterable elements) { + if (elements instanceof Collection) { + return new LinkedHashSet(Collections2.cast(elements)); + } + LinkedHashSet set = Sets.newLinkedHashSet(); + Iterables.addAll(set, elements); + return set; + } + + public static TreeSet newTreeSet() { + return new TreeSet(); + } + + public static TreeSet newTreeSet(Iterable elements) { + TreeSet set = Sets.newTreeSet(); + Iterables.addAll(set, elements); + return set; + } + + public static TreeSet newTreeSet(Comparator comparator) { + return new TreeSet(Preconditions.checkNotNull(comparator)); + } + + public static Set newIdentityHashSet() { + return Sets.newSetFromMap(Maps.newIdentityHashMap()); + } + + @GwtIncompatible(value="CopyOnWriteArraySet") + public static CopyOnWriteArraySet newCopyOnWriteArraySet() { + return new CopyOnWriteArraySet(); + } + + @GwtIncompatible(value="CopyOnWriteArraySet") + public static CopyOnWriteArraySet newCopyOnWriteArraySet(Iterable elements) { + Collection elementsCollection = elements instanceof Collection ? Collections2.cast(elements) : Lists.newArrayList(elements); + return new CopyOnWriteArraySet(elementsCollection); + } + + public static > EnumSet complementOf(Collection collection) { + if (collection instanceof EnumSet) { + return EnumSet.complementOf((EnumSet)collection); + } + Preconditions.checkArgument(!collection.isEmpty(), "collection is empty; use the other version of this method"); + Class type = ((Enum)collection.iterator().next()).getDeclaringClass(); + return Sets.makeComplementByHand(collection, type); + } + + public static > EnumSet complementOf(Collection collection, Class type) { + Preconditions.checkNotNull(collection); + return collection instanceof EnumSet ? EnumSet.complementOf((EnumSet)collection) : Sets.makeComplementByHand(collection, type); + } + + private static > EnumSet makeComplementByHand(Collection collection, Class type) { + EnumSet result = EnumSet.allOf(type); + result.removeAll(collection); + return result; + } + + public static Set newSetFromMap(Map map) { + return Platform.newSetFromMap(map); + } + + public static SetView union(final Set set1, final Set set2) { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + final SetView set2minus1 = Sets.difference(set2, set1); + return new SetView(){ + + @Override + public int size() { + return set1.size() + set2minus1.size(); + } + + @Override + public boolean isEmpty() { + return set1.isEmpty() && set2.isEmpty(); + } + + @Override + public Iterator iterator() { + return Iterators.unmodifiableIterator(Iterators.concat(set1.iterator(), set2minus1.iterator())); + } + + @Override + public boolean contains(Object object) { + return set1.contains(object) || set2.contains(object); + } + + @Override + public > S copyInto(S set) { + set.addAll(set1); + set.addAll(set2); + return set; + } + + @Override + public ImmutableSet immutableCopy() { + return ((ImmutableSet.Builder)((ImmutableSet.Builder)new ImmutableSet.Builder().addAll((Iterable)set1)).addAll((Iterable)set2)).build(); + } + }; + } + + public static SetView intersection(final Set set1, final Set set2) { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + final Predicate inSet2 = Predicates.in(set2); + return new SetView(){ + + @Override + public Iterator iterator() { + return Iterators.filter(set1.iterator(), inSet2); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + + @Override + public boolean isEmpty() { + return !this.iterator().hasNext(); + } + + @Override + public boolean contains(Object object) { + return set1.contains(object) && set2.contains(object); + } + + @Override + public boolean containsAll(Collection collection) { + return set1.containsAll(collection) && set2.containsAll(collection); + } + }; + } + + public static SetView difference(final Set set1, final Set set2) { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + final Predicate notInSet2 = Predicates.not(Predicates.in(set2)); + return new SetView(){ + + @Override + public Iterator iterator() { + return Iterators.filter(set1.iterator(), notInSet2); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + + @Override + public boolean isEmpty() { + return set2.containsAll(set1); + } + + @Override + public boolean contains(Object element) { + return set1.contains(element) && !set2.contains(element); + } + }; + } + + public static SetView symmetricDifference(Set set1, Set set2) { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + return Sets.difference(Sets.union(set1, set2), Sets.intersection(set1, set2)); + } + + public static Set filter(Set unfiltered, Predicate predicate) { + if (unfiltered instanceof SortedSet) { + return Sets.filter((SortedSet)unfiltered, predicate); + } + if (unfiltered instanceof FilteredSet) { + FilteredSet filtered = (FilteredSet)unfiltered; + Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate); + return new FilteredSet((Set)filtered.unfiltered, combinedPredicate); + } + return new FilteredSet(Preconditions.checkNotNull(unfiltered), Preconditions.checkNotNull(predicate)); + } + + public static SortedSet filter(SortedSet unfiltered, Predicate predicate) { + return Platform.setsFilterSortedSet(unfiltered, predicate); + } + + static SortedSet filterSortedIgnoreNavigable(SortedSet unfiltered, Predicate predicate) { + if (unfiltered instanceof FilteredSet) { + FilteredSet filtered = (FilteredSet)((Object)unfiltered); + Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate); + return new FilteredSortedSet((SortedSet)filtered.unfiltered, combinedPredicate); + } + return new FilteredSortedSet(Preconditions.checkNotNull(unfiltered), Preconditions.checkNotNull(predicate)); + } + + @GwtIncompatible(value="NavigableSet") + public static NavigableSet filter(NavigableSet unfiltered, Predicate predicate) { + if (unfiltered instanceof FilteredSet) { + FilteredSet filtered = (FilteredSet)((Object)unfiltered); + Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate); + return new FilteredNavigableSet((NavigableSet)filtered.unfiltered, combinedPredicate); + } + return new FilteredNavigableSet(Preconditions.checkNotNull(unfiltered), Preconditions.checkNotNull(predicate)); + } + + public static Set> cartesianProduct(List> sets) { + return CartesianSet.create(sets); + } + + public static Set> cartesianProduct(Set ... sets) { + return Sets.cartesianProduct(Arrays.asList(sets)); + } + + @GwtCompatible(serializable=false) + public static Set> powerSet(Set set) { + return new PowerSet(set); + } + + static int hashCodeImpl(Set s) { + int hashCode = 0; + for (Object o : s) { + hashCode += o != null ? o.hashCode() : 0; + hashCode = ~(~hashCode); + } + return hashCode; + } + + static boolean equalsImpl(Set s, @Nullable Object object) { + if (s == object) { + return true; + } + if (object instanceof Set) { + Set o = (Set)object; + try { + return s.size() == o.size() && s.containsAll(o); + } + catch (NullPointerException ignored) { + return false; + } + catch (ClassCastException ignored) { + return false; + } + } + return false; + } + + @GwtIncompatible(value="NavigableSet") + public static NavigableSet unmodifiableNavigableSet(NavigableSet set) { + if (set instanceof ImmutableSortedSet || set instanceof UnmodifiableNavigableSet) { + return set; + } + return new UnmodifiableNavigableSet(set); + } + + @GwtIncompatible(value="NavigableSet") + public static NavigableSet synchronizedNavigableSet(NavigableSet navigableSet) { + return Synchronized.navigableSet(navigableSet); + } + + static boolean removeAllImpl(Set set, Iterator iterator) { + boolean changed = false; + while (iterator.hasNext()) { + changed |= set.remove(iterator.next()); + } + return changed; + } + + static boolean removeAllImpl(Set set, Collection collection) { + Preconditions.checkNotNull(collection); + if (collection instanceof Multiset) { + collection = ((Multiset)collection).elementSet(); + } + if (collection instanceof Set && collection.size() > set.size()) { + return Iterators.removeAll(set.iterator(), collection); + } + return Sets.removeAllImpl(set, collection.iterator()); + } + + @GwtIncompatible(value="NavigableSet") + static class DescendingSet + extends ForwardingNavigableSet { + private final NavigableSet forward; + + DescendingSet(NavigableSet forward) { + this.forward = forward; + } + + @Override + protected NavigableSet delegate() { + return this.forward; + } + + @Override + public E lower(E e) { + return this.forward.higher(e); + } + + @Override + public E floor(E e) { + return this.forward.ceiling(e); + } + + @Override + public E ceiling(E e) { + return this.forward.floor(e); + } + + @Override + public E higher(E e) { + return this.forward.lower(e); + } + + @Override + public E pollFirst() { + return this.forward.pollLast(); + } + + @Override + public E pollLast() { + return this.forward.pollFirst(); + } + + @Override + public NavigableSet descendingSet() { + return this.forward; + } + + @Override + public Iterator descendingIterator() { + return this.forward.iterator(); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return this.forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet(); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return this.forward.tailSet(toElement, inclusive).descendingSet(); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return this.forward.headSet(fromElement, inclusive).descendingSet(); + } + + @Override + public Comparator comparator() { + Comparator forwardComparator = this.forward.comparator(); + if (forwardComparator == null) { + return Ordering.natural().reverse(); + } + return DescendingSet.reverse(forwardComparator); + } + + private static Ordering reverse(Comparator forward) { + return Ordering.from(forward).reverse(); + } + + @Override + public E first() { + return this.forward.last(); + } + + @Override + public SortedSet headSet(E toElement) { + return this.standardHeadSet(toElement); + } + + @Override + public E last() { + return this.forward.first(); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return this.standardSubSet(fromElement, toElement); + } + + @Override + public SortedSet tailSet(E fromElement) { + return this.standardTailSet(fromElement); + } + + @Override + public Iterator iterator() { + return this.forward.descendingIterator(); + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + + @Override + public String toString() { + return this.standardToString(); + } + } + + @GwtIncompatible(value="NavigableSet") + static final class UnmodifiableNavigableSet + extends ForwardingSortedSet + implements NavigableSet, + Serializable { + private final NavigableSet delegate; + private transient UnmodifiableNavigableSet descendingSet; + private static final long serialVersionUID = 0L; + + UnmodifiableNavigableSet(NavigableSet delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected SortedSet delegate() { + return Collections.unmodifiableSortedSet(this.delegate); + } + + @Override + public E lower(E e) { + return this.delegate.lower(e); + } + + @Override + public E floor(E e) { + return this.delegate.floor(e); + } + + @Override + public E ceiling(E e) { + return this.delegate.ceiling(e); + } + + @Override + public E higher(E e) { + return this.delegate.higher(e); + } + + @Override + public E pollFirst() { + throw new UnsupportedOperationException(); + } + + @Override + public E pollLast() { + throw new UnsupportedOperationException(); + } + + @Override + public NavigableSet descendingSet() { + UnmodifiableNavigableSet result = this.descendingSet; + if (result == null) { + result = this.descendingSet = new UnmodifiableNavigableSet(this.delegate.descendingSet()); + result.descendingSet = this; + } + return result; + } + + @Override + public Iterator descendingIterator() { + return Iterators.unmodifiableIterator(this.delegate.descendingIterator()); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return Sets.unmodifiableNavigableSet(this.delegate.subSet(fromElement, fromInclusive, toElement, toInclusive)); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return Sets.unmodifiableNavigableSet(this.delegate.headSet(toElement, inclusive)); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return Sets.unmodifiableNavigableSet(this.delegate.tailSet(fromElement, inclusive)); + } + } + + private static final class PowerSet + extends AbstractSet> { + final ImmutableMap inputSet; + + PowerSet(Set input) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + int i = 0; + for (E e : Preconditions.checkNotNull(input)) { + builder.put(e, i++); + } + this.inputSet = builder.build(); + Preconditions.checkArgument(this.inputSet.size() <= 30, "Too many elements to create power set: %s > 30", this.inputSet.size()); + } + + @Override + public int size() { + return 1 << this.inputSet.size(); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Iterator> iterator() { + return new AbstractIndexedListIterator>(this.size()){ + + @Override + protected Set get(int setBits) { + return new SubSet(PowerSet.this.inputSet, setBits); + } + }; + } + + @Override + public boolean contains(@Nullable Object obj) { + if (obj instanceof Set) { + Set set = (Set)obj; + return ((AbstractCollection)((Object)this.inputSet.keySet())).containsAll(set); + } + return false; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof PowerSet) { + PowerSet that = (PowerSet)obj; + return this.inputSet.equals(that.inputSet); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return ((ImmutableSet)this.inputSet.keySet()).hashCode() << this.inputSet.size() - 1; + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.inputSet)); + return new StringBuilder(10 + string.length()).append("powerSet(").append(string).append(")").toString(); + } + } + + private static final class SubSet + extends AbstractSet { + private final ImmutableMap inputSet; + private final int mask; + + SubSet(ImmutableMap inputSet, int mask) { + this.inputSet = inputSet; + this.mask = mask; + } + + @Override + public Iterator iterator() { + return new UnmodifiableIterator(){ + final ImmutableList elements; + int remainingSetBits; + { + this.elements = ((ImmutableCollection)((Object)SubSet.this.inputSet.keySet())).asList(); + this.remainingSetBits = SubSet.this.mask; + } + + @Override + public boolean hasNext() { + return this.remainingSetBits != 0; + } + + @Override + public E next() { + int index = Integer.numberOfTrailingZeros(this.remainingSetBits); + if (index == 32) { + throw new NoSuchElementException(); + } + this.remainingSetBits &= ~(1 << index); + return this.elements.get(index); + } + }; + } + + @Override + public int size() { + return Integer.bitCount(this.mask); + } + + @Override + public boolean contains(@Nullable Object o) { + Integer index = this.inputSet.get(o); + return index != null && (this.mask & 1 << index) != 0; + } + } + + private static final class CartesianSet + extends ForwardingCollection> + implements Set> { + private final transient ImmutableList> axes; + private final transient CartesianList delegate; + + static Set> create(List> sets) { + ImmutableList.Builder axesBuilder = new ImmutableList.Builder(sets.size()); + for (Set set : sets) { + ImmutableSet copy = ImmutableSet.copyOf(set); + if (copy.isEmpty()) { + return ImmutableSet.of(); + } + axesBuilder.add(copy); + } + ImmutableCollection axes = axesBuilder.build(); + ImmutableList immutableList = new ImmutableList>((ImmutableList)axes){ + final /* synthetic */ ImmutableList val$axes; + { + this.val$axes = immutableList; + } + + @Override + public int size() { + return this.val$axes.size(); + } + + @Override + public List get(int index) { + return ((ImmutableSet)this.val$axes.get(index)).asList(); + } + + @Override + boolean isPartialView() { + return true; + } + }; + return new CartesianSet(axes, new CartesianList(immutableList)); + } + + private CartesianSet(ImmutableList> axes, CartesianList delegate) { + this.axes = axes; + this.delegate = delegate; + } + + @Override + protected Collection> delegate() { + return this.delegate; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof CartesianSet) { + CartesianSet that = (CartesianSet)object; + return this.axes.equals(that.axes); + } + return super.equals(object); + } + + @Override + public int hashCode() { + int adjust = this.size() - 1; + for (int i = 0; i < this.axes.size(); ++i) { + adjust *= 31; + adjust = ~(~adjust); + } + int hash = 1; + for (Set set : this.axes) { + hash = 31 * hash + this.size() / set.size() * set.hashCode(); + hash = ~(~hash); + } + return ~(~(hash += adjust)); + } + } + + @GwtIncompatible(value="NavigableSet") + private static class FilteredNavigableSet + extends FilteredSortedSet + implements NavigableSet { + FilteredNavigableSet(NavigableSet unfiltered, Predicate predicate) { + super(unfiltered, predicate); + } + + NavigableSet unfiltered() { + return (NavigableSet)this.unfiltered; + } + + @Override + @Nullable + public E lower(E e) { + return Iterators.getNext(this.headSet(e, false).descendingIterator(), null); + } + + @Override + @Nullable + public E floor(E e) { + return Iterators.getNext(this.headSet(e, true).descendingIterator(), null); + } + + @Override + public E ceiling(E e) { + return Iterables.getFirst(this.tailSet(e, true), null); + } + + @Override + public E higher(E e) { + return Iterables.getFirst(this.tailSet(e, false), null); + } + + @Override + public E pollFirst() { + return Iterables.removeFirstMatching(this.unfiltered(), this.predicate); + } + + @Override + public E pollLast() { + return Iterables.removeFirstMatching(this.unfiltered().descendingSet(), this.predicate); + } + + @Override + public NavigableSet descendingSet() { + return Sets.filter(this.unfiltered().descendingSet(), this.predicate); + } + + @Override + public Iterator descendingIterator() { + return Iterators.filter(this.unfiltered().descendingIterator(), this.predicate); + } + + @Override + public E last() { + return this.descendingIterator().next(); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return Sets.filter(this.unfiltered().subSet(fromElement, fromInclusive, toElement, toInclusive), this.predicate); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return Sets.filter(this.unfiltered().headSet(toElement, inclusive), this.predicate); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return Sets.filter(this.unfiltered().tailSet(fromElement, inclusive), this.predicate); + } + } + + private static class FilteredSortedSet + extends FilteredSet + implements SortedSet { + FilteredSortedSet(SortedSet unfiltered, Predicate predicate) { + super(unfiltered, predicate); + } + + @Override + public Comparator comparator() { + return ((SortedSet)this.unfiltered).comparator(); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return new FilteredSortedSet(((SortedSet)this.unfiltered).subSet(fromElement, toElement), this.predicate); + } + + @Override + public SortedSet headSet(E toElement) { + return new FilteredSortedSet(((SortedSet)this.unfiltered).headSet(toElement), this.predicate); + } + + @Override + public SortedSet tailSet(E fromElement) { + return new FilteredSortedSet(((SortedSet)this.unfiltered).tailSet(fromElement), this.predicate); + } + + @Override + public E first() { + return this.iterator().next(); + } + + @Override + public E last() { + SortedSet sortedUnfiltered = (SortedSet)this.unfiltered; + Object element; + while (!this.predicate.apply(element = sortedUnfiltered.last())) { + sortedUnfiltered = sortedUnfiltered.headSet(element); + } + return element; + } + } + + private static class FilteredSet + extends Collections2.FilteredCollection + implements Set { + FilteredSet(Set unfiltered, Predicate predicate) { + super(unfiltered, predicate); + } + + @Override + public boolean equals(@Nullable Object object) { + return Sets.equalsImpl(this, object); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + public static abstract class SetView + extends AbstractSet { + private SetView() { + } + + public ImmutableSet immutableCopy() { + return ImmutableSet.copyOf(this); + } + + public > S copyInto(S set) { + set.addAll(this); + return set; + } + } + + static abstract class ImprovedAbstractSet + extends AbstractSet { + ImprovedAbstractSet() { + } + + @Override + public boolean removeAll(Collection c) { + return Sets.removeAllImpl(this, c); + } + + @Override + public boolean retainAll(Collection c) { + return super.retainAll(Preconditions.checkNotNull(c)); + } + } +} diff --git a/src/com/google/common/collect/SingletonImmutableBiMap.java b/src/com/google/common/collect/SingletonImmutableBiMap.java new file mode 100644 index 0000000..96a1472 --- /dev/null +++ b/src/com/google/common/collect/SingletonImmutableBiMap.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableBiMap +extends ImmutableBiMap { + final transient K singleKey; + final transient V singleValue; + transient ImmutableBiMap inverse; + + SingletonImmutableBiMap(K singleKey, V singleValue) { + CollectPreconditions.checkEntryNotNull(singleKey, singleValue); + this.singleKey = singleKey; + this.singleValue = singleValue; + } + + private SingletonImmutableBiMap(K singleKey, V singleValue, ImmutableBiMap inverse) { + this.singleKey = singleKey; + this.singleValue = singleValue; + this.inverse = inverse; + } + + SingletonImmutableBiMap(Map.Entry entry) { + this(entry.getKey(), entry.getValue()); + } + + @Override + public V get(@Nullable Object key) { + return this.singleKey.equals(key) ? (V)this.singleValue : null; + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.singleKey.equals(key); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.singleValue.equals(value); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + ImmutableSet> createEntrySet() { + return ImmutableSet.of(Maps.immutableEntry(this.singleKey, this.singleValue)); + } + + @Override + ImmutableSet createKeySet() { + return ImmutableSet.of(this.singleKey); + } + + @Override + public ImmutableBiMap inverse() { + ImmutableBiMap result = this.inverse; + if (result == null) { + this.inverse = new SingletonImmutableBiMap(this.singleValue, this.singleKey, this); + return this.inverse; + } + return result; + } +} diff --git a/src/com/google/common/collect/SingletonImmutableList.java b/src/com/google/common/collect/SingletonImmutableList.java new file mode 100644 index 0000000..47dc98f --- /dev/null +++ b/src/com/google/common/collect/SingletonImmutableList.java @@ -0,0 +1,103 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableIterator; +import java.util.List; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableList +extends ImmutableList { + final transient E element; + + SingletonImmutableList(E element) { + this.element = Preconditions.checkNotNull(element); + } + + @Override + public E get(int index) { + Preconditions.checkElementIndex(index, 1); + return this.element; + } + + @Override + public int indexOf(@Nullable Object object) { + return this.element.equals(object) ? 0 : -1; + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.singletonIterator(this.element); + } + + @Override + public int lastIndexOf(@Nullable Object object) { + return this.indexOf(object); + } + + @Override + public int size() { + return 1; + } + + @Override + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, 1); + return fromIndex == toIndex ? ImmutableList.of() : this; + } + + @Override + public ImmutableList reverse() { + return this; + } + + @Override + public boolean contains(@Nullable Object object) { + return this.element.equals(object); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof List) { + List that = (List)object; + return that.size() == 1 && this.element.equals(that.get(0)); + } + return false; + } + + @Override + public int hashCode() { + return 31 + this.element.hashCode(); + } + + @Override + public String toString() { + String elementToString = this.element.toString(); + return new StringBuilder(elementToString.length() + 2).append('[').append(elementToString).append(']').toString(); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + dst[offset] = this.element; + return offset + 1; + } +} diff --git a/src/com/google/common/collect/SingletonImmutableSet.java b/src/com/google/common/collect/SingletonImmutableSet.java new file mode 100644 index 0000000..e2c3836 --- /dev/null +++ b/src/com/google/common/collect/SingletonImmutableSet.java @@ -0,0 +1,91 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.UnmodifiableIterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableSet +extends ImmutableSet { + final transient E element; + private transient int cachedHashCode; + + SingletonImmutableSet(E element) { + this.element = Preconditions.checkNotNull(element); + } + + SingletonImmutableSet(E element, int hashCode) { + this.element = element; + this.cachedHashCode = hashCode; + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object target) { + return this.element.equals(target); + } + + @Override + public UnmodifiableIterator iterator() { + return Iterators.singletonIterator(this.element); + } + + @Override + boolean isPartialView() { + return false; + } + + @Override + int copyIntoArray(Object[] dst, int offset) { + dst[offset] = this.element; + return offset + 1; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof Set) { + Set that = (Set)object; + return that.size() == 1 && this.element.equals(that.iterator().next()); + } + return false; + } + + @Override + public final int hashCode() { + int code = this.cachedHashCode; + if (code == 0) { + this.cachedHashCode = code = this.element.hashCode(); + } + return code; + } + + @Override + boolean isHashCodeFast() { + return this.cachedHashCode != 0; + } + + @Override + public String toString() { + String elementToString = this.element.toString(); + return new StringBuilder(elementToString.length() + 2).append('[').append(elementToString).append(']').toString(); + } +} diff --git a/src/com/google/common/collect/SingletonImmutableTable.java b/src/com/google/common/collect/SingletonImmutableTable.java new file mode 100644 index 0000000..05f51fd --- /dev/null +++ b/src/com/google/common/collect/SingletonImmutableTable.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import java.util.Map; + +@GwtCompatible +class SingletonImmutableTable +extends ImmutableTable { + final R singleRowKey; + final C singleColumnKey; + final V singleValue; + + SingletonImmutableTable(R rowKey, C columnKey, V value) { + this.singleRowKey = Preconditions.checkNotNull(rowKey); + this.singleColumnKey = Preconditions.checkNotNull(columnKey); + this.singleValue = Preconditions.checkNotNull(value); + } + + SingletonImmutableTable(Table.Cell cell) { + this(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + + @Override + public ImmutableMap column(C columnKey) { + Preconditions.checkNotNull(columnKey); + return this.containsColumn(columnKey) ? ImmutableMap.of(this.singleRowKey, this.singleValue) : ImmutableMap.of(); + } + + @Override + public ImmutableMap> columnMap() { + return ImmutableMap.of(this.singleColumnKey, ImmutableMap.of(this.singleRowKey, this.singleValue)); + } + + @Override + public ImmutableMap> rowMap() { + return ImmutableMap.of(this.singleRowKey, ImmutableMap.of(this.singleColumnKey, this.singleValue)); + } + + @Override + public int size() { + return 1; + } + + @Override + ImmutableSet> createCellSet() { + return ImmutableSet.of(SingletonImmutableTable.cellOf(this.singleRowKey, this.singleColumnKey, this.singleValue)); + } + + @Override + ImmutableCollection createValues() { + return ImmutableSet.of(this.singleValue); + } +} diff --git a/src/com/google/common/collect/SortedIterable.java b/src/com/google/common/collect/SortedIterable.java new file mode 100644 index 0000000..ca065b1 --- /dev/null +++ b/src/com/google/common/collect/SortedIterable.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; + +@GwtCompatible +interface SortedIterable +extends Iterable { + public Comparator comparator(); + + @Override + public Iterator iterator(); +} diff --git a/src/com/google/common/collect/SortedIterables.java b/src/com/google/common/collect/SortedIterables.java new file mode 100644 index 0000000..bc9adcb --- /dev/null +++ b/src/com/google/common/collect/SortedIterables.java @@ -0,0 +1,39 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.Ordering; +import com.google.common.collect.SortedIterable; +import java.util.Comparator; +import java.util.SortedSet; + +@GwtCompatible +final class SortedIterables { + private SortedIterables() { + } + + public static boolean hasSameComparator(Comparator comparator, Iterable elements) { + Comparator comparator2; + Preconditions.checkNotNull(comparator); + Preconditions.checkNotNull(elements); + if (elements instanceof SortedSet) { + comparator2 = SortedIterables.comparator((SortedSet)elements); + } else if (elements instanceof SortedIterable) { + comparator2 = ((SortedIterable)elements).comparator(); + } else { + return false; + } + return comparator.equals(comparator2); + } + + public static Comparator comparator(SortedSet sortedSet) { + Comparator result = sortedSet.comparator(); + if (result == null) { + result = Ordering.natural(); + } + return result; + } +} diff --git a/src/com/google/common/collect/SortedLists.java b/src/com/google/common/collect/SortedLists.java new file mode 100644 index 0000000..e1fe328 --- /dev/null +++ b/src/com/google/common/collect/SortedLists.java @@ -0,0 +1,157 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.Nullable; + +@GwtCompatible +@Beta +final class SortedLists { + private SortedLists() { + } + + public static int binarySearch(List list, E e, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) { + Preconditions.checkNotNull(e); + return SortedLists.binarySearch(list, Preconditions.checkNotNull(e), Ordering.natural(), presentBehavior, absentBehavior); + } + + public static int binarySearch(List list, Function keyFunction, @Nullable K key, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) { + return SortedLists.binarySearch(list, keyFunction, key, Ordering.natural(), presentBehavior, absentBehavior); + } + + public static int binarySearch(List list, Function keyFunction, @Nullable K key, Comparator keyComparator, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) { + return SortedLists.binarySearch(Lists.transform(list, keyFunction), key, keyComparator, presentBehavior, absentBehavior); + } + + public static int binarySearch(List list, @Nullable E key, Comparator comparator, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) { + Preconditions.checkNotNull(comparator); + Preconditions.checkNotNull(list); + Preconditions.checkNotNull(presentBehavior); + Preconditions.checkNotNull(absentBehavior); + if (!(list instanceof RandomAccess)) { + list = Lists.newArrayList(list); + } + int lower = 0; + int upper = list.size() - 1; + while (lower <= upper) { + int middle = lower + upper >>> 1; + int c = comparator.compare(key, list.get(middle)); + if (c < 0) { + upper = middle - 1; + continue; + } + if (c > 0) { + lower = middle + 1; + continue; + } + return lower + presentBehavior.resultIndex(comparator, key, list.subList(lower, upper + 1), middle - lower); + } + return absentBehavior.resultIndex(lower); + } + + public static enum KeyAbsentBehavior { + NEXT_LOWER{ + + @Override + int resultIndex(int higherIndex) { + return higherIndex - 1; + } + } + , + NEXT_HIGHER{ + + @Override + public int resultIndex(int higherIndex) { + return higherIndex; + } + } + , + INVERTED_INSERTION_INDEX{ + + @Override + public int resultIndex(int higherIndex) { + return ~higherIndex; + } + }; + + + abstract int resultIndex(int var1); + } + + public static enum KeyPresentBehavior { + ANY_PRESENT{ + + @Override + int resultIndex(Comparator comparator, E key, List list, int foundIndex) { + return foundIndex; + } + } + , + LAST_PRESENT{ + + @Override + int resultIndex(Comparator comparator, E key, List list, int foundIndex) { + int lower = foundIndex; + int upper = list.size() - 1; + while (lower < upper) { + int middle = lower + upper + 1 >>> 1; + int c = comparator.compare(list.get(middle), key); + if (c > 0) { + upper = middle - 1; + continue; + } + lower = middle; + } + return lower; + } + } + , + FIRST_PRESENT{ + + @Override + int resultIndex(Comparator comparator, E key, List list, int foundIndex) { + int lower = 0; + int upper = foundIndex; + while (lower < upper) { + int middle = lower + upper >>> 1; + int c = comparator.compare(list.get(middle), key); + if (c < 0) { + lower = middle + 1; + continue; + } + upper = middle; + } + return lower; + } + } + , + FIRST_AFTER{ + + @Override + public int resultIndex(Comparator comparator, E key, List list, int foundIndex) { + return LAST_PRESENT.resultIndex(comparator, key, list, foundIndex) + 1; + } + } + , + LAST_BEFORE{ + + @Override + public int resultIndex(Comparator comparator, E key, List list, int foundIndex) { + return FIRST_PRESENT.resultIndex(comparator, key, list, foundIndex) - 1; + } + }; + + + abstract int resultIndex(Comparator var1, E var2, List var3, int var4); + } +} diff --git a/src/com/google/common/collect/SortedMapDifference.java b/src/com/google/common/collect/SortedMapDifference.java new file mode 100644 index 0000000..5935a5e --- /dev/null +++ b/src/com/google/common/collect/SortedMapDifference.java @@ -0,0 +1,24 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.MapDifference; +import java.util.SortedMap; + +@GwtCompatible +public interface SortedMapDifference +extends MapDifference { + @Override + public SortedMap entriesOnlyOnLeft(); + + @Override + public SortedMap entriesOnlyOnRight(); + + @Override + public SortedMap entriesInCommon(); + + @Override + public SortedMap> entriesDiffering(); +} diff --git a/src/com/google/common/collect/SortedMultiset.java b/src/com/google/common/collect/SortedMultiset.java new file mode 100644 index 0000000..dee92ea --- /dev/null +++ b/src/com/google/common/collect/SortedMultiset.java @@ -0,0 +1,49 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.Multiset; +import com.google.common.collect.SortedIterable; +import com.google.common.collect.SortedMultisetBridge; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; + +@Beta +@GwtCompatible(emulated=true) +public interface SortedMultiset +extends SortedMultisetBridge, +SortedIterable { + @Override + public Comparator comparator(); + + public Multiset.Entry firstEntry(); + + public Multiset.Entry lastEntry(); + + public Multiset.Entry pollFirstEntry(); + + public Multiset.Entry pollLastEntry(); + + @Override + public NavigableSet elementSet(); + + @Override + public Set> entrySet(); + + @Override + public Iterator iterator(); + + public SortedMultiset descendingMultiset(); + + public SortedMultiset headMultiset(E var1, BoundType var2); + + public SortedMultiset subMultiset(E var1, BoundType var2, E var3, BoundType var4); + + public SortedMultiset tailMultiset(E var1, BoundType var2); +} diff --git a/src/com/google/common/collect/SortedMultisetBridge.java b/src/com/google/common/collect/SortedMultisetBridge.java new file mode 100644 index 0000000..3d04227 --- /dev/null +++ b/src/com/google/common/collect/SortedMultisetBridge.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.collect.Multiset; +import java.util.SortedSet; + +interface SortedMultisetBridge +extends Multiset { + @Override + public SortedSet elementSet(); +} diff --git a/src/com/google/common/collect/SortedMultisets.java b/src/com/google/common/collect/SortedMultisets.java new file mode 100644 index 0000000..9459981 --- /dev/null +++ b/src/com/google/common/collect/SortedMultisets.java @@ -0,0 +1,143 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.SortedMultiset; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class SortedMultisets { + private SortedMultisets() { + } + + private static E getElementOrThrow(Multiset.Entry entry) { + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getElement(); + } + + private static E getElementOrNull(@Nullable Multiset.Entry entry) { + return entry == null ? null : (E)entry.getElement(); + } + + @GwtIncompatible(value="Navigable") + static class NavigableElementSet + extends ElementSet + implements NavigableSet { + NavigableElementSet(SortedMultiset multiset) { + super(multiset); + } + + @Override + public E lower(E e) { + return (E)SortedMultisets.getElementOrNull(this.multiset().headMultiset(e, BoundType.OPEN).lastEntry()); + } + + @Override + public E floor(E e) { + return (E)SortedMultisets.getElementOrNull(this.multiset().headMultiset(e, BoundType.CLOSED).lastEntry()); + } + + @Override + public E ceiling(E e) { + return (E)SortedMultisets.getElementOrNull(this.multiset().tailMultiset(e, BoundType.CLOSED).firstEntry()); + } + + @Override + public E higher(E e) { + return (E)SortedMultisets.getElementOrNull(this.multiset().tailMultiset(e, BoundType.OPEN).firstEntry()); + } + + @Override + public NavigableSet descendingSet() { + return new NavigableElementSet(this.multiset().descendingMultiset()); + } + + @Override + public Iterator descendingIterator() { + return this.descendingSet().iterator(); + } + + @Override + public E pollFirst() { + return (E)SortedMultisets.getElementOrNull(this.multiset().pollFirstEntry()); + } + + @Override + public E pollLast() { + return (E)SortedMultisets.getElementOrNull(this.multiset().pollLastEntry()); + } + + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + return new NavigableElementSet(this.multiset().subMultiset(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + return new NavigableElementSet(this.multiset().headMultiset(toElement, BoundType.forBoolean(inclusive))); + } + + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + return new NavigableElementSet(this.multiset().tailMultiset(fromElement, BoundType.forBoolean(inclusive))); + } + } + + static class ElementSet + extends Multisets.ElementSet + implements SortedSet { + private final SortedMultiset multiset; + + ElementSet(SortedMultiset multiset) { + this.multiset = multiset; + } + + @Override + final SortedMultiset multiset() { + return this.multiset; + } + + @Override + public Comparator comparator() { + return this.multiset().comparator(); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return this.multiset().subMultiset(fromElement, BoundType.CLOSED, toElement, BoundType.OPEN).elementSet(); + } + + @Override + public SortedSet headSet(E toElement) { + return this.multiset().headMultiset(toElement, BoundType.OPEN).elementSet(); + } + + @Override + public SortedSet tailSet(E fromElement) { + return this.multiset().tailMultiset(fromElement, BoundType.CLOSED).elementSet(); + } + + @Override + public E first() { + return (E)SortedMultisets.getElementOrThrow(this.multiset().firstEntry()); + } + + @Override + public E last() { + return (E)SortedMultisets.getElementOrThrow(this.multiset().lastEntry()); + } + } +} diff --git a/src/com/google/common/collect/SortedSetMultimap.java b/src/com/google/common/collect/SortedSetMultimap.java new file mode 100644 index 0000000..e6150a8 --- /dev/null +++ b/src/com/google/common/collect/SortedSetMultimap.java @@ -0,0 +1,30 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.SetMultimap; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public interface SortedSetMultimap +extends SetMultimap { + @Override + public SortedSet get(@Nullable K var1); + + @Override + public SortedSet removeAll(@Nullable Object var1); + + @Override + public SortedSet replaceValues(K var1, Iterable var2); + + @Override + public Map> asMap(); + + public Comparator valueComparator(); +} diff --git a/src/com/google/common/collect/SparseImmutableTable.java b/src/com/google/common/collect/SparseImmutableTable.java new file mode 100644 index 0000000..315b160 --- /dev/null +++ b/src/com/google/common/collect/SparseImmutableTable.java @@ -0,0 +1,105 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.RegularImmutableTable; +import com.google.common.collect.Table; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +@GwtCompatible +@Immutable +final class SparseImmutableTable +extends RegularImmutableTable { + private final ImmutableMap> rowMap; + private final ImmutableMap> columnMap; + private final int[] iterationOrderRow; + private final int[] iterationOrderColumn; + + SparseImmutableTable(ImmutableList> cellList, ImmutableSet rowSpace, ImmutableSet columnSpace) { + HashMap rowIndex = Maps.newHashMap(); + LinkedHashMap rows = Maps.newLinkedHashMap(); + for (Object row : rowSpace) { + rowIndex.put(row, rows.size()); + rows.put(row, new LinkedHashMap()); + } + LinkedHashMap columns = Maps.newLinkedHashMap(); + for (Object col : columnSpace) { + columns.put(col, new LinkedHashMap()); + } + int[] iterationOrderRow = new int[cellList.size()]; + int[] iterationOrderColumn = new int[cellList.size()]; + for (int i = 0; i < cellList.size(); ++i) { + Table.Cell cell = (Table.Cell)cellList.get(i); + Object rowKey = cell.getRowKey(); + Object columnKey = cell.getColumnKey(); + Object value = cell.getValue(); + iterationOrderRow[i] = (Integer)rowIndex.get(rowKey); + Map thisRow = (Map)rows.get(rowKey); + iterationOrderColumn[i] = thisRow.size(); + Object oldValue = thisRow.put(columnKey, value); + if (oldValue != null) { + String string = String.valueOf(String.valueOf(rowKey)); + String string2 = String.valueOf(String.valueOf(columnKey)); + String string3 = String.valueOf(String.valueOf(value)); + String string4 = String.valueOf(String.valueOf(oldValue)); + throw new IllegalArgumentException(new StringBuilder(37 + string.length() + string2.length() + string3.length() + string4.length()).append("Duplicate value for row=").append(string).append(", column=").append(string2).append(": ").append(string3).append(", ").append(string4).toString()); + } + ((Map)columns.get(columnKey)).put(rowKey, value); + } + this.iterationOrderRow = iterationOrderRow; + this.iterationOrderColumn = iterationOrderColumn; + ImmutableMap.Builder rowBuilder = ImmutableMap.builder(); + for (Map.Entry row : rows.entrySet()) { + rowBuilder.put(row.getKey(), ImmutableMap.copyOf((Map)row.getValue())); + } + this.rowMap = rowBuilder.build(); + ImmutableMap.Builder columnBuilder = ImmutableMap.builder(); + for (Map.Entry col : columns.entrySet()) { + columnBuilder.put(col.getKey(), ImmutableMap.copyOf((Map)col.getValue())); + } + this.columnMap = columnBuilder.build(); + } + + @Override + public ImmutableMap> columnMap() { + return this.columnMap; + } + + @Override + public ImmutableMap> rowMap() { + return this.rowMap; + } + + @Override + public int size() { + return this.iterationOrderRow.length; + } + + @Override + Table.Cell getCell(int index) { + int rowIndex = this.iterationOrderRow[index]; + Map.Entry rowEntry = (Map.Entry)((ImmutableCollection)((Object)this.rowMap.entrySet())).asList().get(rowIndex); + ImmutableMap row = (ImmutableMap)rowEntry.getValue(); + int columnIndex = this.iterationOrderColumn[index]; + Map.Entry colEntry = (Map.Entry)((ImmutableCollection)((Object)row.entrySet())).asList().get(columnIndex); + return SparseImmutableTable.cellOf(rowEntry.getKey(), colEntry.getKey(), colEntry.getValue()); + } + + @Override + V getValue(int index) { + int rowIndex = this.iterationOrderRow[index]; + ImmutableMap row = (ImmutableMap)((ImmutableCollection)this.rowMap.values()).asList().get(rowIndex); + int columnIndex = this.iterationOrderColumn[index]; + return (V)((ImmutableCollection)row.values()).asList().get(columnIndex); + } +} diff --git a/src/com/google/common/collect/StandardRowSortedTable.java b/src/com/google/common/collect/StandardRowSortedTable.java new file mode 100644 index 0000000..c6b07ca --- /dev/null +++ b/src/com/google/common/collect/StandardRowSortedTable.java @@ -0,0 +1,97 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.Maps; +import com.google.common.collect.RowSortedTable; +import com.google.common.collect.StandardTable; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + +@GwtCompatible +class StandardRowSortedTable +extends StandardTable +implements RowSortedTable { + private static final long serialVersionUID = 0L; + + StandardRowSortedTable(SortedMap> backingMap, Supplier> factory) { + super(backingMap, factory); + } + + private SortedMap> sortedBackingMap() { + return (SortedMap)this.backingMap; + } + + @Override + public SortedSet rowKeySet() { + return (SortedSet)this.rowMap().keySet(); + } + + @Override + public SortedMap> rowMap() { + return (SortedMap)super.rowMap(); + } + + @Override + SortedMap> createRowMap() { + return new RowSortedMap(); + } + + private class RowSortedMap + extends StandardTable.RowMap + implements SortedMap> { + private RowSortedMap() { + super(StandardRowSortedTable.this); + } + + @Override + public SortedSet keySet() { + return (SortedSet)super.keySet(); + } + + @Override + SortedSet createKeySet() { + return new Maps.SortedKeySet(this); + } + + @Override + public Comparator comparator() { + return StandardRowSortedTable.this.sortedBackingMap().comparator(); + } + + @Override + public R firstKey() { + return StandardRowSortedTable.this.sortedBackingMap().firstKey(); + } + + @Override + public R lastKey() { + return StandardRowSortedTable.this.sortedBackingMap().lastKey(); + } + + @Override + public SortedMap> headMap(R toKey) { + Preconditions.checkNotNull(toKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().headMap(toKey), StandardRowSortedTable.this.factory).rowMap(); + } + + @Override + public SortedMap> subMap(R fromKey, R toKey) { + Preconditions.checkNotNull(fromKey); + Preconditions.checkNotNull(toKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().subMap(fromKey, toKey), StandardRowSortedTable.this.factory).rowMap(); + } + + @Override + public SortedMap> tailMap(R fromKey) { + Preconditions.checkNotNull(fromKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().tailMap(fromKey), StandardRowSortedTable.this.factory).rowMap(); + } + } +} diff --git a/src/com/google/common/collect/StandardTable.java b/src/com/google/common/collect/StandardTable.java new file mode 100644 index 0000000..553e84b --- /dev/null +++ b/src/com/google/common/collect/StandardTable.java @@ -0,0 +1,898 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.AbstractTable; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.GwtTransient; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.collect.Table; +import com.google.common.collect.Tables; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +class StandardTable +extends AbstractTable +implements Serializable { + @GwtTransient + final Map> backingMap; + @GwtTransient + final Supplier> factory; + private transient Set columnKeySet; + private transient Map> rowMap; + private transient ColumnMap columnMap; + private static final long serialVersionUID = 0L; + + StandardTable(Map> backingMap, Supplier> factory) { + this.backingMap = backingMap; + this.factory = factory; + } + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + return rowKey != null && columnKey != null && super.contains(rowKey, columnKey); + } + + @Override + public boolean containsColumn(@Nullable Object columnKey) { + if (columnKey == null) { + return false; + } + for (Map map : this.backingMap.values()) { + if (!Maps.safeContainsKey(map, columnKey)) continue; + return true; + } + return false; + } + + @Override + public boolean containsRow(@Nullable Object rowKey) { + return rowKey != null && Maps.safeContainsKey(this.backingMap, rowKey); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return value != null && super.containsValue(value); + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + return rowKey == null || columnKey == null ? null : (V)super.get(rowKey, columnKey); + } + + @Override + public boolean isEmpty() { + return this.backingMap.isEmpty(); + } + + @Override + public int size() { + int size = 0; + for (Map map : this.backingMap.values()) { + size += map.size(); + } + return size; + } + + @Override + public void clear() { + this.backingMap.clear(); + } + + private Map getOrCreate(R rowKey) { + Map map = this.backingMap.get(rowKey); + if (map == null) { + map = this.factory.get(); + this.backingMap.put(rowKey, map); + } + return map; + } + + @Override + public V put(R rowKey, C columnKey, V value) { + Preconditions.checkNotNull(rowKey); + Preconditions.checkNotNull(columnKey); + Preconditions.checkNotNull(value); + return this.getOrCreate(rowKey).put(columnKey, value); + } + + @Override + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) { + if (rowKey == null || columnKey == null) { + return null; + } + Map map = Maps.safeGet(this.backingMap, rowKey); + if (map == null) { + return null; + } + V value = map.remove(columnKey); + if (map.isEmpty()) { + this.backingMap.remove(rowKey); + } + return value; + } + + private Map removeColumn(Object column) { + LinkedHashMap output = new LinkedHashMap(); + Iterator>> iterator = this.backingMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry> entry = iterator.next(); + V value = entry.getValue().remove(column); + if (value == null) continue; + output.put(entry.getKey(), value); + if (!entry.getValue().isEmpty()) continue; + iterator.remove(); + } + return output; + } + + private boolean containsMapping(Object rowKey, Object columnKey, Object value) { + return value != null && value.equals(this.get(rowKey, columnKey)); + } + + private boolean removeMapping(Object rowKey, Object columnKey, Object value) { + if (this.containsMapping(rowKey, columnKey, value)) { + this.remove(rowKey, columnKey); + return true; + } + return false; + } + + @Override + public Set> cellSet() { + return super.cellSet(); + } + + @Override + Iterator> cellIterator() { + return new CellIterator(); + } + + @Override + public Map row(R rowKey) { + return new Row(rowKey); + } + + @Override + public Map column(C columnKey) { + return new Column(columnKey); + } + + @Override + public Set rowKeySet() { + return this.rowMap().keySet(); + } + + @Override + public Set columnKeySet() { + ColumnKeySet result = this.columnKeySet; + return result == null ? (this.columnKeySet = new ColumnKeySet()) : result; + } + + Iterator createColumnKeyIterator() { + return new ColumnKeyIterator(); + } + + @Override + public Collection values() { + return super.values(); + } + + @Override + public Map> rowMap() { + Map>> result = this.rowMap; + return result == null ? (this.rowMap = this.createRowMap()) : result; + } + + Map> createRowMap() { + return new RowMap(); + } + + @Override + public Map> columnMap() { + ColumnMap result = this.columnMap; + return result == null ? (this.columnMap = new ColumnMap()) : result; + } + + private class ColumnMap + extends Maps.ImprovedAbstractMap> { + private ColumnMap() { + } + + @Override + public Map get(Object key) { + return StandardTable.this.containsColumn(key) ? StandardTable.this.column(key) : null; + } + + @Override + public boolean containsKey(Object key) { + return StandardTable.this.containsColumn(key); + } + + @Override + public Map remove(Object key) { + return StandardTable.this.containsColumn(key) ? StandardTable.this.removeColumn(key) : null; + } + + @Override + public Set>> createEntrySet() { + return new ColumnMapEntrySet(); + } + + @Override + public Set keySet() { + return StandardTable.this.columnKeySet(); + } + + @Override + Collection> createValues() { + return new ColumnMapValues(); + } + + private class ColumnMapValues + extends Maps.Values> { + ColumnMapValues() { + super(ColumnMap.this); + } + + @Override + public boolean remove(Object obj) { + for (Map.Entry entry : ColumnMap.this.entrySet()) { + if (!((Map)entry.getValue()).equals(obj)) continue; + StandardTable.this.removeColumn(entry.getKey()); + return true; + } + return false; + } + + @Override + public boolean removeAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (Object columnKey : Lists.newArrayList(StandardTable.this.columnKeySet().iterator())) { + if (!c.contains(StandardTable.this.column(columnKey))) continue; + StandardTable.this.removeColumn(columnKey); + changed = true; + } + return changed; + } + + @Override + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (Object columnKey : Lists.newArrayList(StandardTable.this.columnKeySet().iterator())) { + if (c.contains(StandardTable.this.column(columnKey))) continue; + StandardTable.this.removeColumn(columnKey); + changed = true; + } + return changed; + } + } + + class ColumnMapEntrySet + extends TableSet>> { + ColumnMapEntrySet() { + } + + @Override + public Iterator>> iterator() { + return Maps.asMapEntryIterator(StandardTable.this.columnKeySet(), new Function>(){ + + @Override + public Map apply(C columnKey) { + return StandardTable.this.column(columnKey); + } + }); + } + + @Override + public int size() { + return StandardTable.this.columnKeySet().size(); + } + + @Override + public boolean contains(Object obj) { + Map.Entry entry; + if (obj instanceof Map.Entry && StandardTable.this.containsColumn((entry = (Map.Entry)obj).getKey())) { + Object columnKey = entry.getKey(); + return ColumnMap.this.get(columnKey).equals(entry.getValue()); + } + return false; + } + + @Override + public boolean remove(Object obj) { + if (this.contains(obj)) { + Map.Entry entry = (Map.Entry)obj; + StandardTable.this.removeColumn(entry.getKey()); + return true; + } + return false; + } + + @Override + public boolean removeAll(Collection c) { + Preconditions.checkNotNull(c); + return Sets.removeAllImpl(this, c.iterator()); + } + + @Override + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (Object columnKey : Lists.newArrayList(StandardTable.this.columnKeySet().iterator())) { + if (c.contains(Maps.immutableEntry(columnKey, StandardTable.this.column(columnKey)))) continue; + StandardTable.this.removeColumn(columnKey); + changed = true; + } + return changed; + } + } + } + + class RowMap + extends Maps.ImprovedAbstractMap> { + RowMap() { + } + + @Override + public boolean containsKey(Object key) { + return StandardTable.this.containsRow(key); + } + + @Override + public Map get(Object key) { + return StandardTable.this.containsRow(key) ? StandardTable.this.row(key) : null; + } + + @Override + public Map remove(Object key) { + return key == null ? null : StandardTable.this.backingMap.remove(key); + } + + @Override + protected Set>> createEntrySet() { + return new EntrySet(); + } + + class EntrySet + extends TableSet>> { + EntrySet() { + } + + @Override + public Iterator>> iterator() { + return Maps.asMapEntryIterator(StandardTable.this.backingMap.keySet(), new Function>(){ + + @Override + public Map apply(R rowKey) { + return StandardTable.this.row(rowKey); + } + }); + } + + @Override + public int size() { + return StandardTable.this.backingMap.size(); + } + + @Override + public boolean contains(Object obj) { + if (obj instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)obj; + return entry.getKey() != null && entry.getValue() instanceof Map && Collections2.safeContains(StandardTable.this.backingMap.entrySet(), entry); + } + return false; + } + + @Override + public boolean remove(Object obj) { + if (obj instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)obj; + return entry.getKey() != null && entry.getValue() instanceof Map && StandardTable.this.backingMap.entrySet().remove(entry); + } + return false; + } + } + } + + private class ColumnKeyIterator + extends AbstractIterator { + final Map seen; + final Iterator> mapIterator; + Iterator> entryIterator; + + private ColumnKeyIterator() { + this.seen = StandardTable.this.factory.get(); + this.mapIterator = StandardTable.this.backingMap.values().iterator(); + this.entryIterator = Iterators.emptyIterator(); + } + + @Override + protected C computeNext() { + while (true) { + if (this.entryIterator.hasNext()) { + Map.Entry entry = this.entryIterator.next(); + if (this.seen.containsKey(entry.getKey())) continue; + this.seen.put(entry.getKey(), entry.getValue()); + return entry.getKey(); + } + if (!this.mapIterator.hasNext()) break; + this.entryIterator = this.mapIterator.next().entrySet().iterator(); + } + return this.endOfData(); + } + } + + private class ColumnKeySet + extends TableSet { + private ColumnKeySet() { + } + + @Override + public Iterator iterator() { + return StandardTable.this.createColumnKeyIterator(); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + + @Override + public boolean remove(Object obj) { + if (obj == null) { + return false; + } + boolean changed = false; + Iterator iterator = StandardTable.this.backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = iterator.next(); + if (!map.keySet().remove(obj)) continue; + changed = true; + if (!map.isEmpty()) continue; + iterator.remove(); + } + return changed; + } + + @Override + public boolean removeAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + Iterator iterator = StandardTable.this.backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = iterator.next(); + if (!Iterators.removeAll(map.keySet().iterator(), c)) continue; + changed = true; + if (!map.isEmpty()) continue; + iterator.remove(); + } + return changed; + } + + @Override + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + Iterator iterator = StandardTable.this.backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = iterator.next(); + if (!map.keySet().retainAll(c)) continue; + changed = true; + if (!map.isEmpty()) continue; + iterator.remove(); + } + return changed; + } + + @Override + public boolean contains(Object obj) { + return StandardTable.this.containsColumn(obj); + } + } + + private class Column + extends Maps.ImprovedAbstractMap { + final C columnKey; + + Column(C columnKey) { + this.columnKey = Preconditions.checkNotNull(columnKey); + } + + @Override + public V put(R key, V value) { + return StandardTable.this.put(key, this.columnKey, value); + } + + @Override + public V get(Object key) { + return StandardTable.this.get(key, this.columnKey); + } + + @Override + public boolean containsKey(Object key) { + return StandardTable.this.contains(key, this.columnKey); + } + + @Override + public V remove(Object key) { + return StandardTable.this.remove(key, this.columnKey); + } + + boolean removeFromColumnIf(Predicate> predicate) { + boolean changed = false; + Iterator iterator = StandardTable.this.backingMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + Map map = entry.getValue(); + Object value = map.get(this.columnKey); + if (value == null || !predicate.apply(Maps.immutableEntry(entry.getKey(), value))) continue; + map.remove(this.columnKey); + changed = true; + if (!map.isEmpty()) continue; + iterator.remove(); + } + return changed; + } + + @Override + Set> createEntrySet() { + return new EntrySet(); + } + + @Override + Set createKeySet() { + return new KeySet(); + } + + @Override + Collection createValues() { + return new Values(); + } + + private class Values + extends Maps.Values { + Values() { + super(Column.this); + } + + @Override + public boolean remove(Object obj) { + return obj != null && Column.this.removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.equalTo(obj))); + } + + @Override + public boolean removeAll(Collection c) { + return Column.this.removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.in(c))); + } + + @Override + public boolean retainAll(Collection c) { + return Column.this.removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + } + + private class KeySet + extends Maps.KeySet { + KeySet() { + super(Column.this); + } + + @Override + public boolean contains(Object obj) { + return StandardTable.this.contains(obj, Column.this.columnKey); + } + + @Override + public boolean remove(Object obj) { + return StandardTable.this.remove(obj, Column.this.columnKey) != null; + } + + @Override + public boolean retainAll(Collection c) { + return Column.this.removeFromColumnIf(Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + } + + private class EntrySetIterator + extends AbstractIterator> { + final Iterator>> iterator; + + private EntrySetIterator() { + this.iterator = StandardTable.this.backingMap.entrySet().iterator(); + } + + @Override + protected Map.Entry computeNext() { + while (this.iterator.hasNext()) { + final Map.Entry entry = this.iterator.next(); + if (!entry.getValue().containsKey(Column.this.columnKey)) continue; + return new AbstractMapEntry(){ + + @Override + public R getKey() { + return entry.getKey(); + } + + @Override + public V getValue() { + return ((Map)entry.getValue()).get(Column.this.columnKey); + } + + @Override + public V setValue(V value) { + return ((Map)entry.getValue()).put(Column.this.columnKey, Preconditions.checkNotNull(value)); + } + }; + } + return (Map.Entry)this.endOfData(); + } + } + + private class EntrySet + extends Sets.ImprovedAbstractSet> { + private EntrySet() { + } + + @Override + public Iterator> iterator() { + return new EntrySetIterator(); + } + + @Override + public int size() { + int size = 0; + for (Map map : StandardTable.this.backingMap.values()) { + if (!map.containsKey(Column.this.columnKey)) continue; + ++size; + } + return size; + } + + @Override + public boolean isEmpty() { + return !StandardTable.this.containsColumn(Column.this.columnKey); + } + + @Override + public void clear() { + Column.this.removeFromColumnIf(Predicates.alwaysTrue()); + } + + @Override + public boolean contains(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)o; + return StandardTable.this.containsMapping(entry.getKey(), Column.this.columnKey, entry.getValue()); + } + return false; + } + + @Override + public boolean remove(Object obj) { + if (obj instanceof Map.Entry) { + Map.Entry entry = (Map.Entry)obj; + return StandardTable.this.removeMapping(entry.getKey(), Column.this.columnKey, entry.getValue()); + } + return false; + } + + @Override + public boolean retainAll(Collection c) { + return Column.this.removeFromColumnIf(Predicates.not(Predicates.in(c))); + } + } + } + + class Row + extends Maps.ImprovedAbstractMap { + final R rowKey; + Map backingRowMap; + + Row(R rowKey) { + this.rowKey = Preconditions.checkNotNull(rowKey); + } + + Map backingRowMap() { + Map map; + if (this.backingRowMap == null || this.backingRowMap.isEmpty() && StandardTable.this.backingMap.containsKey(this.rowKey)) { + this.backingRowMap = this.computeBackingRowMap(); + map = this.backingRowMap; + } else { + map = this.backingRowMap; + } + return map; + } + + Map computeBackingRowMap() { + return StandardTable.this.backingMap.get(this.rowKey); + } + + void maintainEmptyInvariant() { + if (this.backingRowMap() != null && this.backingRowMap.isEmpty()) { + StandardTable.this.backingMap.remove(this.rowKey); + this.backingRowMap = null; + } + } + + @Override + public boolean containsKey(Object key) { + Map backingRowMap = this.backingRowMap(); + return key != null && backingRowMap != null && Maps.safeContainsKey(backingRowMap, key); + } + + @Override + public V get(Object key) { + Map backingRowMap = this.backingRowMap(); + return key != null && backingRowMap != null ? (Object)Maps.safeGet(backingRowMap, key) : null; + } + + @Override + public V put(C key, V value) { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + if (this.backingRowMap != null && !this.backingRowMap.isEmpty()) { + return this.backingRowMap.put(key, value); + } + return StandardTable.this.put(this.rowKey, key, value); + } + + @Override + public V remove(Object key) { + Map backingRowMap = this.backingRowMap(); + if (backingRowMap == null) { + return null; + } + Object result = Maps.safeRemove(backingRowMap, key); + this.maintainEmptyInvariant(); + return result; + } + + @Override + public void clear() { + Map backingRowMap = this.backingRowMap(); + if (backingRowMap != null) { + backingRowMap.clear(); + } + this.maintainEmptyInvariant(); + } + + @Override + protected Set> createEntrySet() { + return new RowEntrySet(); + } + + private final class RowEntrySet + extends Maps.EntrySet { + private RowEntrySet() { + } + + @Override + Map map() { + return Row.this; + } + + @Override + public int size() { + Map map = Row.this.backingRowMap(); + return map == null ? 0 : map.size(); + } + + @Override + public Iterator> iterator() { + Map map = Row.this.backingRowMap(); + if (map == null) { + return Iterators.emptyModifiableIterator(); + } + final Iterator iterator = map.entrySet().iterator(); + return new Iterator>(){ + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Map.Entry next() { + final Map.Entry entry = (Map.Entry)iterator.next(); + return new ForwardingMapEntry(){ + + @Override + protected Map.Entry delegate() { + return entry; + } + + @Override + public V setValue(V value) { + return super.setValue(Preconditions.checkNotNull(value)); + } + + @Override + public boolean equals(Object object) { + return this.standardEquals(object); + } + }; + } + + @Override + public void remove() { + iterator.remove(); + Row.this.maintainEmptyInvariant(); + } + }; + } + } + } + + private class CellIterator + implements Iterator> { + final Iterator>> rowIterator; + Map.Entry> rowEntry; + Iterator> columnIterator; + + private CellIterator() { + this.rowIterator = StandardTable.this.backingMap.entrySet().iterator(); + this.columnIterator = Iterators.emptyModifiableIterator(); + } + + @Override + public boolean hasNext() { + return this.rowIterator.hasNext() || this.columnIterator.hasNext(); + } + + @Override + public Table.Cell next() { + if (!this.columnIterator.hasNext()) { + this.rowEntry = this.rowIterator.next(); + this.columnIterator = this.rowEntry.getValue().entrySet().iterator(); + } + Map.Entry columnEntry = this.columnIterator.next(); + return Tables.immutableCell(this.rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue()); + } + + @Override + public void remove() { + this.columnIterator.remove(); + if (this.rowEntry.getValue().isEmpty()) { + this.rowIterator.remove(); + } + } + } + + private abstract class TableSet + extends Sets.ImprovedAbstractSet { + private TableSet() { + } + + @Override + public boolean isEmpty() { + return StandardTable.this.backingMap.isEmpty(); + } + + @Override + public void clear() { + StandardTable.this.backingMap.clear(); + } + } +} diff --git a/src/com/google/common/collect/Synchronized.java b/src/com/google/common/collect/Synchronized.java new file mode 100644 index 0000000..b801ea4 --- /dev/null +++ b/src/com/google/common/collect/Synchronized.java @@ -0,0 +1,2471 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingIterator; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Iterators; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedSetMultimap; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.Deque; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Queue; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +final class Synchronized { + private Synchronized() { + } + + private static Collection collection(Collection collection, @Nullable Object mutex) { + return new SynchronizedCollection(collection, mutex); + } + + @VisibleForTesting + static Set set(Set set, @Nullable Object mutex) { + return new SynchronizedSet(set, mutex); + } + + private static SortedSet sortedSet(SortedSet set, @Nullable Object mutex) { + return new SynchronizedSortedSet(set, mutex); + } + + private static List list(List list, @Nullable Object mutex) { + return list instanceof RandomAccess ? new SynchronizedRandomAccessList(list, mutex) : new SynchronizedList(list, mutex); + } + + static Multiset multiset(Multiset multiset, @Nullable Object mutex) { + if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) { + return multiset; + } + return new SynchronizedMultiset(multiset, mutex); + } + + static Multimap multimap(Multimap multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedMultimap || multimap instanceof ImmutableMultimap) { + return multimap; + } + return new SynchronizedMultimap(multimap, mutex); + } + + static ListMultimap listMultimap(ListMultimap multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedListMultimap || multimap instanceof ImmutableListMultimap) { + return multimap; + } + return new SynchronizedListMultimap(multimap, mutex); + } + + static SetMultimap setMultimap(SetMultimap multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedSetMultimap || multimap instanceof ImmutableSetMultimap) { + return multimap; + } + return new SynchronizedSetMultimap(multimap, mutex); + } + + static SortedSetMultimap sortedSetMultimap(SortedSetMultimap multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedSortedSetMultimap) { + return multimap; + } + return new SynchronizedSortedSetMultimap(multimap, mutex); + } + + private static Collection typePreservingCollection(Collection collection, @Nullable Object mutex) { + if (collection instanceof SortedSet) { + return Synchronized.sortedSet((SortedSet)collection, mutex); + } + if (collection instanceof Set) { + return Synchronized.set((Set)collection, mutex); + } + if (collection instanceof List) { + return Synchronized.list((List)collection, mutex); + } + return Synchronized.collection(collection, mutex); + } + + private static Set typePreservingSet(Set set, @Nullable Object mutex) { + if (set instanceof SortedSet) { + return Synchronized.sortedSet((SortedSet)set, mutex); + } + return Synchronized.set(set, mutex); + } + + @VisibleForTesting + static Map map(Map map, @Nullable Object mutex) { + return new SynchronizedMap(map, mutex); + } + + static SortedMap sortedMap(SortedMap sortedMap, @Nullable Object mutex) { + return new SynchronizedSortedMap(sortedMap, mutex); + } + + static BiMap biMap(BiMap bimap, @Nullable Object mutex) { + if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) { + return bimap; + } + return new SynchronizedBiMap(bimap, mutex, null); + } + + @GwtIncompatible(value="NavigableSet") + static NavigableSet navigableSet(NavigableSet navigableSet, @Nullable Object mutex) { + return new SynchronizedNavigableSet(navigableSet, mutex); + } + + @GwtIncompatible(value="NavigableSet") + static NavigableSet navigableSet(NavigableSet navigableSet) { + return Synchronized.navigableSet(navigableSet, null); + } + + @GwtIncompatible(value="NavigableMap") + static NavigableMap navigableMap(NavigableMap navigableMap) { + return Synchronized.navigableMap(navigableMap, null); + } + + @GwtIncompatible(value="NavigableMap") + static NavigableMap navigableMap(NavigableMap navigableMap, @Nullable Object mutex) { + return new SynchronizedNavigableMap(navigableMap, mutex); + } + + @GwtIncompatible(value="works but is needed only for NavigableMap") + private static Map.Entry nullableSynchronizedEntry(@Nullable Map.Entry entry, @Nullable Object mutex) { + if (entry == null) { + return null; + } + return new SynchronizedEntry(entry, mutex); + } + + static Queue queue(Queue queue, @Nullable Object mutex) { + return queue instanceof SynchronizedQueue ? queue : new SynchronizedQueue(queue, mutex); + } + + @GwtIncompatible(value="Deque") + static Deque deque(Deque deque, @Nullable Object mutex) { + return new SynchronizedDeque(deque, mutex); + } + + @GwtIncompatible(value="Deque") + private static final class SynchronizedDeque + extends SynchronizedQueue + implements Deque { + private static final long serialVersionUID = 0L; + + SynchronizedDeque(Deque delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Deque delegate() { + return (Deque)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void addFirst(E e) { + Object object = this.mutex; + synchronized (object) { + this.delegate().addFirst(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void addLast(E e) { + Object object = this.mutex; + synchronized (object) { + this.delegate().addLast(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean offerFirst(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().offerFirst(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean offerLast(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().offerLast(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E removeFirst() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeFirst(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E removeLast() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeLast(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E pollFirst() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().pollFirst(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E pollLast() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().pollLast(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E getFirst() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().getFirst(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E getLast() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().getLast(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E peekFirst() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().peekFirst(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E peekLast() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().peekLast(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean removeFirstOccurrence(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeFirstOccurrence(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean removeLastOccurrence(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeLastOccurrence(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void push(E e) { + Object object = this.mutex; + synchronized (object) { + this.delegate().push(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E pop() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().pop(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Iterator descendingIterator() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().descendingIterator(); + } + } + } + + private static class SynchronizedQueue + extends SynchronizedCollection + implements Queue { + private static final long serialVersionUID = 0L; + + SynchronizedQueue(Queue delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Queue delegate() { + return (Queue)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E element() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().element(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean offer(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().offer(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E peek() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().peek(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E poll() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().poll(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E remove() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(); + } + } + } + + @GwtIncompatible(value="works but is needed only for NavigableMap") + private static class SynchronizedEntry + extends SynchronizedObject + implements Map.Entry { + private static final long serialVersionUID = 0L; + + SynchronizedEntry(Map.Entry delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Map.Entry delegate() { + return (Map.Entry)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object obj) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(obj); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K getKey() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().getKey(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V getValue() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().getValue(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V setValue(V value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().setValue(value); + } + } + } + + @GwtIncompatible(value="NavigableMap") + @VisibleForTesting + static class SynchronizedNavigableMap + extends SynchronizedSortedMap + implements NavigableMap { + transient NavigableSet descendingKeySet; + transient NavigableMap descendingMap; + transient NavigableSet navigableKeySet; + private static final long serialVersionUID = 0L; + + SynchronizedNavigableMap(NavigableMap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + NavigableMap delegate() { + return (NavigableMap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry ceilingEntry(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().ceilingEntry(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K ceilingKey(K key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().ceilingKey(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet descendingKeySet() { + Object object = this.mutex; + synchronized (object) { + if (this.descendingKeySet == null) { + this.descendingKeySet = Synchronized.navigableSet(this.delegate().descendingKeySet(), this.mutex); + return this.descendingKeySet; + } + return this.descendingKeySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableMap descendingMap() { + Object object = this.mutex; + synchronized (object) { + if (this.descendingMap == null) { + this.descendingMap = Synchronized.navigableMap(this.delegate().descendingMap(), this.mutex); + return this.descendingMap; + } + return this.descendingMap; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry firstEntry() { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().firstEntry(), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry floorEntry(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().floorEntry(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K floorKey(K key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().floorKey(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableMap(this.delegate().headMap(toKey, inclusive), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry higherEntry(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().higherEntry(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K higherKey(K key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().higherKey(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry lastEntry() { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().lastEntry(), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry lowerEntry(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().lowerEntry(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K lowerKey(K key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().lowerKey(key); + } + } + + @Override + public Set keySet() { + return this.navigableKeySet(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet navigableKeySet() { + Object object = this.mutex; + synchronized (object) { + if (this.navigableKeySet == null) { + this.navigableKeySet = Synchronized.navigableSet(this.delegate().navigableKeySet(), this.mutex); + return this.navigableKeySet; + } + return this.navigableKeySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry pollFirstEntry() { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().pollFirstEntry(), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map.Entry pollLastEntry() { + Object object = this.mutex; + synchronized (object) { + return Synchronized.nullableSynchronizedEntry(this.delegate().pollLastEntry(), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableMap(this.delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableMap(this.delegate().tailMap(fromKey, inclusive), this.mutex); + } + } + + @Override + public SortedMap headMap(K toKey) { + return this.headMap(toKey, false); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + return this.subMap(fromKey, true, toKey, false); + } + + @Override + public SortedMap tailMap(K fromKey) { + return this.tailMap(fromKey, true); + } + } + + @GwtIncompatible(value="NavigableSet") + @VisibleForTesting + static class SynchronizedNavigableSet + extends SynchronizedSortedSet + implements NavigableSet { + transient NavigableSet descendingSet; + private static final long serialVersionUID = 0L; + + SynchronizedNavigableSet(NavigableSet delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + NavigableSet delegate() { + return (NavigableSet)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E ceiling(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().ceiling(e); + } + } + + @Override + public Iterator descendingIterator() { + return this.delegate().descendingIterator(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet descendingSet() { + Object object = this.mutex; + synchronized (object) { + if (this.descendingSet == null) { + NavigableSet dS = Synchronized.navigableSet(this.delegate().descendingSet(), this.mutex); + this.descendingSet = dS; + return dS; + } + return this.descendingSet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E floor(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().floor(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet headSet(E toElement, boolean inclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableSet(this.delegate().headSet(toElement, inclusive), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E higher(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().higher(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E lower(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().lower(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E pollFirst() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().pollFirst(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E pollLast() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().pollLast(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableSet(this.delegate().subSet(fromElement, fromInclusive, toElement, toInclusive), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public NavigableSet tailSet(E fromElement, boolean inclusive) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.navigableSet(this.delegate().tailSet(fromElement, inclusive), this.mutex); + } + } + + @Override + public SortedSet headSet(E toElement) { + return this.headSet(toElement, false); + } + + @Override + public SortedSet subSet(E fromElement, E toElement) { + return this.subSet(fromElement, true, toElement, false); + } + + @Override + public SortedSet tailSet(E fromElement) { + return this.tailSet(fromElement, true); + } + } + + private static class SynchronizedAsMapValues + extends SynchronizedCollection> { + private static final long serialVersionUID = 0L; + + SynchronizedAsMapValues(Collection> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + public Iterator> iterator() { + final Iterator iterator = super.iterator(); + return new ForwardingIterator>(){ + + @Override + protected Iterator> delegate() { + return iterator; + } + + @Override + public Collection next() { + return Synchronized.typePreservingCollection((Collection)super.next(), SynchronizedAsMapValues.this.mutex); + } + }; + } + } + + private static class SynchronizedAsMap + extends SynchronizedMap> { + transient Set>> asMapEntrySet; + transient Collection> asMapValues; + private static final long serialVersionUID = 0L; + + SynchronizedAsMap(Map> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection get(Object key) { + Object object = this.mutex; + synchronized (object) { + Collection collection = (Collection)super.get(key); + return collection == null ? null : Synchronized.typePreservingCollection(collection, this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set>> entrySet() { + Object object = this.mutex; + synchronized (object) { + if (this.asMapEntrySet == null) { + this.asMapEntrySet = new SynchronizedAsMapEntries(this.delegate().entrySet(), this.mutex); + } + return this.asMapEntrySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection> values() { + Object object = this.mutex; + synchronized (object) { + if (this.asMapValues == null) { + this.asMapValues = new SynchronizedAsMapValues(this.delegate().values(), this.mutex); + } + return this.asMapValues; + } + } + + @Override + public boolean containsValue(Object o) { + return this.values().contains(o); + } + } + + @VisibleForTesting + static class SynchronizedBiMap + extends SynchronizedMap + implements BiMap, + Serializable { + private transient Set valueSet; + private transient BiMap inverse; + private static final long serialVersionUID = 0L; + + private SynchronizedBiMap(BiMap delegate, @Nullable Object mutex, @Nullable BiMap inverse) { + super(delegate, mutex); + this.inverse = inverse; + } + + @Override + BiMap delegate() { + return (BiMap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set values() { + Object object = this.mutex; + synchronized (object) { + if (this.valueSet == null) { + this.valueSet = Synchronized.set(this.delegate().values(), this.mutex); + } + return this.valueSet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V forcePut(K key, V value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().forcePut(key, value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public BiMap inverse() { + Object object = this.mutex; + synchronized (object) { + if (this.inverse == null) { + this.inverse = new SynchronizedBiMap(this.delegate().inverse(), this.mutex, this); + } + return this.inverse; + } + } + } + + static class SynchronizedSortedMap + extends SynchronizedMap + implements SortedMap { + private static final long serialVersionUID = 0L; + + SynchronizedSortedMap(SortedMap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + SortedMap delegate() { + return (SortedMap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Comparator comparator() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().comparator(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K firstKey() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().firstKey(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedMap headMap(K toKey) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedMap(this.delegate().headMap(toKey), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public K lastKey() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().lastKey(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedMap subMap(K fromKey, K toKey) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedMap(this.delegate().subMap(fromKey, toKey), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedMap tailMap(K fromKey) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedMap(this.delegate().tailMap(fromKey), this.mutex); + } + } + } + + private static class SynchronizedMap + extends SynchronizedObject + implements Map { + transient Set keySet; + transient Collection values; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedMap(Map delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Map delegate() { + return (Map)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void clear() { + Object object = this.mutex; + synchronized (object) { + this.delegate().clear(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsKey(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsKey(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsValue(Object value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsValue(value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set> entrySet() { + Object object = this.mutex; + synchronized (object) { + if (this.entrySet == null) { + this.entrySet = Synchronized.set(this.delegate().entrySet(), this.mutex); + } + return this.entrySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V get(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().get(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean isEmpty() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().isEmpty(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set keySet() { + Object object = this.mutex; + synchronized (object) { + if (this.keySet == null) { + this.keySet = Synchronized.set(this.delegate().keySet(), this.mutex); + } + return this.keySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V put(K key, V value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().put(key, value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void putAll(Map map) { + Object object = this.mutex; + synchronized (object) { + this.delegate().putAll(map); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public V remove(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int size() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().size(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection values() { + Object object = this.mutex; + synchronized (object) { + if (this.values == null) { + this.values = Synchronized.collection(this.delegate().values(), this.mutex); + } + return this.values; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + } + + private static class SynchronizedAsMapEntries + extends SynchronizedSet>> { + private static final long serialVersionUID = 0L; + + SynchronizedAsMapEntries(Set>> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + public Iterator>> iterator() { + final Iterator iterator = super.iterator(); + return new ForwardingIterator>>(){ + + @Override + protected Iterator>> delegate() { + return iterator; + } + + @Override + public Map.Entry> next() { + final Map.Entry entry = (Map.Entry)super.next(); + return new ForwardingMapEntry>(){ + + @Override + protected Map.Entry> delegate() { + return entry; + } + + @Override + public Collection getValue() { + return Synchronized.typePreservingCollection((Collection)entry.getValue(), SynchronizedAsMapEntries.this.mutex); + } + }; + } + }; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Object[] toArray() { + Object object = this.mutex; + synchronized (object) { + return ObjectArrays.toArrayImpl(this.delegate()); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T[] toArray(T[] array) { + Object object = this.mutex; + synchronized (object) { + return ObjectArrays.toArrayImpl(this.delegate(), array); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean contains(Object o) { + Object object = this.mutex; + synchronized (object) { + return Maps.containsEntryImpl(this.delegate(), o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return Collections2.containsAllImpl(this.delegate(), c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return Sets.equalsImpl(this.delegate(), o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean remove(Object o) { + Object object = this.mutex; + synchronized (object) { + return Maps.removeEntryImpl(this.delegate(), o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean removeAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return Iterators.removeAll(this.delegate().iterator(), c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean retainAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return Iterators.retainAll(this.delegate().iterator(), c); + } + } + } + + private static class SynchronizedSortedSetMultimap + extends SynchronizedSetMultimap + implements SortedSetMultimap { + private static final long serialVersionUID = 0L; + + SynchronizedSortedSetMultimap(SortedSetMultimap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + SortedSetMultimap delegate() { + return (SortedSetMultimap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet get(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedSet(this.delegate().get(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet removeAll(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeAll(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet replaceValues(K key, Iterable values) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().replaceValues(key, values); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Comparator valueComparator() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().valueComparator(); + } + } + } + + private static class SynchronizedSetMultimap + extends SynchronizedMultimap + implements SetMultimap { + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedSetMultimap(SetMultimap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + SetMultimap delegate() { + return (SetMultimap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set get(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.set(this.delegate().get(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set removeAll(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeAll(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set replaceValues(K key, Iterable values) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().replaceValues(key, values); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set> entries() { + Object object = this.mutex; + synchronized (object) { + if (this.entrySet == null) { + this.entrySet = Synchronized.set(this.delegate().entries(), this.mutex); + } + return this.entrySet; + } + } + } + + private static class SynchronizedListMultimap + extends SynchronizedMultimap + implements ListMultimap { + private static final long serialVersionUID = 0L; + + SynchronizedListMultimap(ListMultimap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + ListMultimap delegate() { + return (ListMultimap)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public List get(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.list(this.delegate().get(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public List removeAll(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeAll(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public List replaceValues(K key, Iterable values) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().replaceValues(key, values); + } + } + } + + private static class SynchronizedMultimap + extends SynchronizedObject + implements Multimap { + transient Set keySet; + transient Collection valuesCollection; + transient Collection> entries; + transient Map> asMap; + transient Multiset keys; + private static final long serialVersionUID = 0L; + + @Override + Multimap delegate() { + return (Multimap)super.delegate(); + } + + SynchronizedMultimap(Multimap delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int size() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().size(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean isEmpty() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().isEmpty(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsKey(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsKey(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsValue(Object value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsValue(value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsEntry(Object key, Object value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsEntry(key, value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection get(K key) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.typePreservingCollection(this.delegate().get(key), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean put(K key, V value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().put(key, value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean putAll(K key, Iterable values) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().putAll(key, values); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean putAll(Multimap multimap) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().putAll(multimap); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection replaceValues(K key, Iterable values) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().replaceValues(key, values); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean remove(Object key, Object value) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(key, value); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection removeAll(Object key) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeAll(key); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void clear() { + Object object = this.mutex; + synchronized (object) { + this.delegate().clear(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set keySet() { + Object object = this.mutex; + synchronized (object) { + if (this.keySet == null) { + this.keySet = Synchronized.typePreservingSet(this.delegate().keySet(), this.mutex); + } + return this.keySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection values() { + Object object = this.mutex; + synchronized (object) { + if (this.valuesCollection == null) { + this.valuesCollection = Synchronized.collection(this.delegate().values(), this.mutex); + } + return this.valuesCollection; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Collection> entries() { + Object object = this.mutex; + synchronized (object) { + if (this.entries == null) { + this.entries = Synchronized.typePreservingCollection(this.delegate().entries(), this.mutex); + } + return this.entries; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Map> asMap() { + Object object = this.mutex; + synchronized (object) { + if (this.asMap == null) { + this.asMap = new SynchronizedAsMap(this.delegate().asMap(), this.mutex); + } + return this.asMap; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Multiset keys() { + Object object = this.mutex; + synchronized (object) { + if (this.keys == null) { + this.keys = Synchronized.multiset(this.delegate().keys(), this.mutex); + } + return this.keys; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + } + + private static class SynchronizedMultiset + extends SynchronizedCollection + implements Multiset { + transient Set elementSet; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedMultiset(Multiset delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Multiset delegate() { + return (Multiset)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int count(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().count(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int add(E e, int n) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().add(e, n); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int remove(Object o, int n) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(o, n); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int setCount(E element, int count) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().setCount(element, count); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean setCount(E element, int oldCount, int newCount) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().setCount(element, oldCount, newCount); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set elementSet() { + Object object = this.mutex; + synchronized (object) { + if (this.elementSet == null) { + this.elementSet = Synchronized.typePreservingSet(this.delegate().elementSet(), this.mutex); + } + return this.elementSet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Set> entrySet() { + Object object = this.mutex; + synchronized (object) { + if (this.entrySet == null) { + this.entrySet = Synchronized.typePreservingSet(this.delegate().entrySet(), this.mutex); + } + return this.entrySet; + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + } + + private static class SynchronizedRandomAccessList + extends SynchronizedList + implements RandomAccess { + private static final long serialVersionUID = 0L; + + SynchronizedRandomAccessList(List list, @Nullable Object mutex) { + super(list, mutex); + } + } + + private static class SynchronizedList + extends SynchronizedCollection + implements List { + private static final long serialVersionUID = 0L; + + SynchronizedList(List delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + List delegate() { + return (List)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void add(int index, E element) { + Object object = this.mutex; + synchronized (object) { + this.delegate().add(index, element); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean addAll(int index, Collection c) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().addAll(index, c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E get(int index) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().get(index); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int indexOf(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().indexOf(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int lastIndexOf(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().lastIndexOf(o); + } + } + + @Override + public ListIterator listIterator() { + return this.delegate().listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return this.delegate().listIterator(index); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E remove(int index) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(index); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E set(int index, E element) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().set(index, element); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public List subList(int fromIndex, int toIndex) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.list(this.delegate().subList(fromIndex, toIndex), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + } + + static class SynchronizedSortedSet + extends SynchronizedSet + implements SortedSet { + private static final long serialVersionUID = 0L; + + SynchronizedSortedSet(SortedSet delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + SortedSet delegate() { + return (SortedSet)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Comparator comparator() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().comparator(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet subSet(E fromElement, E toElement) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedSet(this.delegate().subSet(fromElement, toElement), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet headSet(E toElement) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedSet(this.delegate().headSet(toElement), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public SortedSet tailSet(E fromElement) { + Object object = this.mutex; + synchronized (object) { + return Synchronized.sortedSet(this.delegate().tailSet(fromElement), this.mutex); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E first() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().first(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public E last() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().last(); + } + } + } + + static class SynchronizedSet + extends SynchronizedCollection + implements Set { + private static final long serialVersionUID = 0L; + + SynchronizedSet(Set delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Set delegate() { + return (Set)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + Object object = this.mutex; + synchronized (object) { + return this.delegate().equals(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int hashCode() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().hashCode(); + } + } + } + + @VisibleForTesting + static class SynchronizedCollection + extends SynchronizedObject + implements Collection { + private static final long serialVersionUID = 0L; + + private SynchronizedCollection(Collection delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + Collection delegate() { + return (Collection)super.delegate(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean add(E e) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().add(e); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean addAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().addAll(c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void clear() { + Object object = this.mutex; + synchronized (object) { + this.delegate().clear(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean contains(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().contains(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean containsAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().containsAll(c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean isEmpty() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().isEmpty(); + } + } + + @Override + public Iterator iterator() { + return this.delegate().iterator(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean remove(Object o) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().remove(o); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean removeAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().removeAll(c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean retainAll(Collection c) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().retainAll(c); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public int size() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().size(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public Object[] toArray() { + Object object = this.mutex; + synchronized (object) { + return this.delegate().toArray(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T[] toArray(T[] a) { + Object object = this.mutex; + synchronized (object) { + return this.delegate().toArray(a); + } + } + } + + static class SynchronizedObject + implements Serializable { + final Object delegate; + final Object mutex; + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 0L; + + SynchronizedObject(Object delegate, @Nullable Object mutex) { + this.delegate = Preconditions.checkNotNull(delegate); + this.mutex = mutex == null ? this : mutex; + } + + Object delegate() { + return this.delegate; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public String toString() { + Object object = this.mutex; + synchronized (object) { + return this.delegate.toString(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + Object object = this.mutex; + synchronized (object) { + stream.defaultWriteObject(); + } + } + } +} diff --git a/src/com/google/common/collect/Table.java b/src/com/google/common/collect/Table.java new file mode 100644 index 0000000..92f33b0 --- /dev/null +++ b/src/com/google/common/collect/Table.java @@ -0,0 +1,67 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public interface Table { + public boolean contains(@Nullable Object var1, @Nullable Object var2); + + public boolean containsRow(@Nullable Object var1); + + public boolean containsColumn(@Nullable Object var1); + + public boolean containsValue(@Nullable Object var1); + + public V get(@Nullable Object var1, @Nullable Object var2); + + public boolean isEmpty(); + + public int size(); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + + public void clear(); + + public V put(R var1, C var2, V var3); + + public void putAll(Table var1); + + public V remove(@Nullable Object var1, @Nullable Object var2); + + public Map row(R var1); + + public Map column(C var1); + + public Set> cellSet(); + + public Set rowKeySet(); + + public Set columnKeySet(); + + public Collection values(); + + public Map> rowMap(); + + public Map> columnMap(); + + public static interface Cell { + public R getRowKey(); + + public C getColumnKey(); + + public V getValue(); + + public boolean equals(@Nullable Object var1); + + public int hashCode(); + } +} diff --git a/src/com/google/common/collect/Tables.java b/src/com/google/common/collect/Tables.java new file mode 100644 index 0000000..e38a45e --- /dev/null +++ b/src/com/google/common/collect/Tables.java @@ -0,0 +1,466 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.AbstractTable; +import com.google.common.collect.Collections2; +import com.google.common.collect.ForwardingTable; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.RowSortedTable; +import com.google.common.collect.StandardTable; +import com.google.common.collect.Table; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public final class Tables { + private static final Function, ? extends Map> UNMODIFIABLE_WRAPPER = new Function, Map>(){ + + @Override + public Map apply(Map input) { + return Collections.unmodifiableMap(input); + } + }; + + private Tables() { + } + + public static Table.Cell immutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) { + return new ImmutableCell(rowKey, columnKey, value); + } + + public static Table transpose(Table table) { + return table instanceof TransposeTable ? ((TransposeTable)table).original : new TransposeTable(table); + } + + @Beta + public static Table newCustomTable(Map> backingMap, Supplier> factory) { + Preconditions.checkArgument(backingMap.isEmpty()); + Preconditions.checkNotNull(factory); + return new StandardTable(backingMap, factory); + } + + @Beta + public static Table transformValues(Table fromTable, Function function) { + return new TransformedTable(fromTable, function); + } + + public static Table unmodifiableTable(Table table) { + return new UnmodifiableTable(table); + } + + @Beta + public static RowSortedTable unmodifiableRowSortedTable(RowSortedTable table) { + return new UnmodifiableRowSortedMap(table); + } + + private static Function, Map> unmodifiableWrapper() { + return UNMODIFIABLE_WRAPPER; + } + + static boolean equalsImpl(Table table, @Nullable Object obj) { + if (obj == table) { + return true; + } + if (obj instanceof Table) { + Table that = (Table)obj; + return table.cellSet().equals(that.cellSet()); + } + return false; + } + + static final class UnmodifiableRowSortedMap + extends UnmodifiableTable + implements RowSortedTable { + private static final long serialVersionUID = 0L; + + public UnmodifiableRowSortedMap(RowSortedTable delegate) { + super(delegate); + } + + @Override + protected RowSortedTable delegate() { + return (RowSortedTable)super.delegate(); + } + + @Override + public SortedMap> rowMap() { + Function wrapper = Tables.unmodifiableWrapper(); + return Collections.unmodifiableSortedMap(Maps.transformValues(this.delegate().rowMap(), wrapper)); + } + + @Override + public SortedSet rowKeySet() { + return Collections.unmodifiableSortedSet(this.delegate().rowKeySet()); + } + } + + private static class UnmodifiableTable + extends ForwardingTable + implements Serializable { + final Table delegate; + private static final long serialVersionUID = 0L; + + UnmodifiableTable(Table delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected Table delegate() { + return this.delegate; + } + + @Override + public Set> cellSet() { + return Collections.unmodifiableSet(super.cellSet()); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public Map column(@Nullable C columnKey) { + return Collections.unmodifiableMap(super.column(columnKey)); + } + + @Override + public Set columnKeySet() { + return Collections.unmodifiableSet(super.columnKeySet()); + } + + @Override + public Map> columnMap() { + Function wrapper = Tables.unmodifiableWrapper(); + return Collections.unmodifiableMap(Maps.transformValues(super.columnMap(), wrapper)); + } + + @Override + public V put(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(Table table) { + throw new UnsupportedOperationException(); + } + + @Override + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) { + throw new UnsupportedOperationException(); + } + + @Override + public Map row(@Nullable R rowKey) { + return Collections.unmodifiableMap(super.row(rowKey)); + } + + @Override + public Set rowKeySet() { + return Collections.unmodifiableSet(super.rowKeySet()); + } + + @Override + public Map> rowMap() { + Function wrapper = Tables.unmodifiableWrapper(); + return Collections.unmodifiableMap(Maps.transformValues(super.rowMap(), wrapper)); + } + + @Override + public Collection values() { + return Collections.unmodifiableCollection(super.values()); + } + } + + private static class TransformedTable + extends AbstractTable { + final Table fromTable; + final Function function; + + TransformedTable(Table fromTable, Function function) { + this.fromTable = Preconditions.checkNotNull(fromTable); + this.function = Preconditions.checkNotNull(function); + } + + @Override + public boolean contains(Object rowKey, Object columnKey) { + return this.fromTable.contains(rowKey, columnKey); + } + + @Override + public V2 get(Object rowKey, Object columnKey) { + return this.contains(rowKey, columnKey) ? (V2)this.function.apply((V1)this.fromTable.get(rowKey, columnKey)) : null; + } + + @Override + public int size() { + return this.fromTable.size(); + } + + @Override + public void clear() { + this.fromTable.clear(); + } + + @Override + public V2 put(R rowKey, C columnKey, V2 value) { + throw new UnsupportedOperationException(); + } + + @Override + public void putAll(Table table) { + throw new UnsupportedOperationException(); + } + + @Override + public V2 remove(Object rowKey, Object columnKey) { + return this.contains(rowKey, columnKey) ? (V2)this.function.apply((V1)this.fromTable.remove(rowKey, columnKey)) : null; + } + + @Override + public Map row(R rowKey) { + return Maps.transformValues(this.fromTable.row(rowKey), this.function); + } + + @Override + public Map column(C columnKey) { + return Maps.transformValues(this.fromTable.column(columnKey), this.function); + } + + Function, Table.Cell> cellFunction() { + return new Function, Table.Cell>(){ + + @Override + public Table.Cell apply(Table.Cell cell) { + return Tables.immutableCell(cell.getRowKey(), cell.getColumnKey(), TransformedTable.this.function.apply(cell.getValue())); + } + }; + } + + @Override + Iterator> cellIterator() { + return Iterators.transform(this.fromTable.cellSet().iterator(), this.cellFunction()); + } + + @Override + public Set rowKeySet() { + return this.fromTable.rowKeySet(); + } + + @Override + public Set columnKeySet() { + return this.fromTable.columnKeySet(); + } + + @Override + Collection createValues() { + return Collections2.transform(this.fromTable.values(), this.function); + } + + @Override + public Map> rowMap() { + Function rowFunction = new Function, Map>(){ + + @Override + public Map apply(Map row) { + return Maps.transformValues(row, TransformedTable.this.function); + } + }; + return Maps.transformValues(this.fromTable.rowMap(), rowFunction); + } + + @Override + public Map> columnMap() { + Function columnFunction = new Function, Map>(){ + + @Override + public Map apply(Map column) { + return Maps.transformValues(column, TransformedTable.this.function); + } + }; + return Maps.transformValues(this.fromTable.columnMap(), columnFunction); + } + } + + private static class TransposeTable + extends AbstractTable { + final Table original; + private static final Function, Table.Cell> TRANSPOSE_CELL = new Function, Table.Cell>(){ + + @Override + public Table.Cell apply(Table.Cell cell) { + return Tables.immutableCell(cell.getColumnKey(), cell.getRowKey(), cell.getValue()); + } + }; + + TransposeTable(Table original) { + this.original = Preconditions.checkNotNull(original); + } + + @Override + public void clear() { + this.original.clear(); + } + + @Override + public Map column(R columnKey) { + return this.original.row(columnKey); + } + + @Override + public Set columnKeySet() { + return this.original.rowKeySet(); + } + + @Override + public Map> columnMap() { + return this.original.rowMap(); + } + + @Override + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) { + return this.original.contains(columnKey, rowKey); + } + + @Override + public boolean containsColumn(@Nullable Object columnKey) { + return this.original.containsRow(columnKey); + } + + @Override + public boolean containsRow(@Nullable Object rowKey) { + return this.original.containsColumn(rowKey); + } + + @Override + public boolean containsValue(@Nullable Object value) { + return this.original.containsValue(value); + } + + @Override + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + return this.original.get(columnKey, rowKey); + } + + @Override + public V put(C rowKey, R columnKey, V value) { + return this.original.put(columnKey, rowKey, value); + } + + @Override + public void putAll(Table table) { + this.original.putAll(Tables.transpose(table)); + } + + @Override + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) { + return this.original.remove(columnKey, rowKey); + } + + @Override + public Map row(C rowKey) { + return this.original.column(rowKey); + } + + @Override + public Set rowKeySet() { + return this.original.columnKeySet(); + } + + @Override + public Map> rowMap() { + return this.original.columnMap(); + } + + @Override + public int size() { + return this.original.size(); + } + + @Override + public Collection values() { + return this.original.values(); + } + + @Override + Iterator> cellIterator() { + return Iterators.transform(this.original.cellSet().iterator(), TRANSPOSE_CELL); + } + } + + static abstract class AbstractCell + implements Table.Cell { + AbstractCell() { + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Table.Cell) { + Table.Cell other = (Table.Cell)obj; + return Objects.equal(this.getRowKey(), other.getRowKey()) && Objects.equal(this.getColumnKey(), other.getColumnKey()) && Objects.equal(this.getValue(), other.getValue()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getRowKey(), this.getColumnKey(), this.getValue()); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.getRowKey())); + String string2 = String.valueOf(String.valueOf(this.getColumnKey())); + String string3 = String.valueOf(String.valueOf(this.getValue())); + return new StringBuilder(4 + string.length() + string2.length() + string3.length()).append("(").append(string).append(",").append(string2).append(")=").append(string3).toString(); + } + } + + static final class ImmutableCell + extends AbstractCell + implements Serializable { + private final R rowKey; + private final C columnKey; + private final V value; + private static final long serialVersionUID = 0L; + + ImmutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) { + this.rowKey = rowKey; + this.columnKey = columnKey; + this.value = value; + } + + @Override + public R getRowKey() { + return this.rowKey; + } + + @Override + public C getColumnKey() { + return this.columnKey; + } + + @Override + public V getValue() { + return this.value; + } + } +} diff --git a/src/com/google/common/collect/TransformedIterator.java b/src/com/google/common/collect/TransformedIterator.java new file mode 100644 index 0000000..25d4423 --- /dev/null +++ b/src/com/google/common/collect/TransformedIterator.java @@ -0,0 +1,35 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Iterator; + +@GwtCompatible +abstract class TransformedIterator +implements Iterator { + final Iterator backingIterator; + + TransformedIterator(Iterator backingIterator) { + this.backingIterator = Preconditions.checkNotNull(backingIterator); + } + + abstract T transform(F var1); + + @Override + public final boolean hasNext() { + return this.backingIterator.hasNext(); + } + + @Override + public final T next() { + return this.transform(this.backingIterator.next()); + } + + @Override + public final void remove() { + this.backingIterator.remove(); + } +} diff --git a/src/com/google/common/collect/TransformedListIterator.java b/src/com/google/common/collect/TransformedListIterator.java new file mode 100644 index 0000000..026a4db --- /dev/null +++ b/src/com/google/common/collect/TransformedListIterator.java @@ -0,0 +1,52 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Iterators; +import com.google.common.collect.TransformedIterator; +import java.util.ListIterator; + +@GwtCompatible +abstract class TransformedListIterator +extends TransformedIterator +implements ListIterator { + TransformedListIterator(ListIterator backingIterator) { + super(backingIterator); + } + + private ListIterator backingIterator() { + return Iterators.cast(this.backingIterator); + } + + @Override + public final boolean hasPrevious() { + return this.backingIterator().hasPrevious(); + } + + @Override + public final T previous() { + return this.transform(this.backingIterator().previous()); + } + + @Override + public final int nextIndex() { + return this.backingIterator().nextIndex(); + } + + @Override + public final int previousIndex() { + return this.backingIterator().previousIndex(); + } + + @Override + public void set(T element) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(T element) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/TreeBasedTable.java b/src/com/google/common/collect/TreeBasedTable.java new file mode 100644 index 0000000..9ca4a5d --- /dev/null +++ b/src/com/google/common/collect/TreeBasedTable.java @@ -0,0 +1,245 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.StandardRowSortedTable; +import com.google.common.collect.StandardTable; +import com.google.common.collect.Table; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +@Beta +public class TreeBasedTable +extends StandardRowSortedTable { + private final Comparator columnComparator; + private static final long serialVersionUID = 0L; + + public static TreeBasedTable create() { + return new TreeBasedTable(Ordering.natural(), Ordering.natural()); + } + + public static TreeBasedTable create(Comparator rowComparator, Comparator columnComparator) { + Preconditions.checkNotNull(rowComparator); + Preconditions.checkNotNull(columnComparator); + return new TreeBasedTable(rowComparator, columnComparator); + } + + public static TreeBasedTable create(TreeBasedTable table) { + TreeBasedTable result = new TreeBasedTable(table.rowComparator(), table.columnComparator()); + result.putAll((Table)table); + return result; + } + + TreeBasedTable(Comparator rowComparator, Comparator columnComparator) { + super(new TreeMap(rowComparator), new Factory(columnComparator)); + this.columnComparator = columnComparator; + } + + public Comparator rowComparator() { + return this.rowKeySet().comparator(); + } + + public Comparator columnComparator() { + return this.columnComparator; + } + + @Override + public SortedMap row(R rowKey) { + return new TreeRow(rowKey); + } + + @Override + public SortedSet rowKeySet() { + return super.rowKeySet(); + } + + @Override + public SortedMap> rowMap() { + return super.rowMap(); + } + + @Override + Iterator createColumnKeyIterator() { + final Comparator comparator = this.columnComparator(); + final UnmodifiableIterator merged = Iterators.mergeSorted(Iterables.transform(this.backingMap.values(), new Function, Iterator>(){ + + @Override + public Iterator apply(Map input) { + return input.keySet().iterator(); + } + }), comparator); + return new AbstractIterator(){ + C lastValue; + + @Override + protected C computeNext() { + while (merged.hasNext()) { + Object next = merged.next(); + boolean duplicate = this.lastValue != null && comparator.compare(next, this.lastValue) == 0; + if (duplicate) continue; + this.lastValue = next; + return this.lastValue; + } + this.lastValue = null; + return this.endOfData(); + } + }; + } + + private class TreeRow + extends StandardTable.Row + implements SortedMap { + @Nullable + final C lowerBound; + @Nullable + final C upperBound; + transient SortedMap wholeRow; + + TreeRow(R rowKey) { + this(rowKey, null, null); + } + + TreeRow(@Nullable R rowKey, @Nullable C lowerBound, C upperBound) { + super(TreeBasedTable.this, rowKey); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + Preconditions.checkArgument(lowerBound == null || upperBound == null || this.compare(lowerBound, upperBound) <= 0); + } + + @Override + public SortedSet keySet() { + return new Maps.SortedKeySet(this); + } + + @Override + public Comparator comparator() { + return TreeBasedTable.this.columnComparator(); + } + + int compare(Object a, Object b) { + Comparator cmp = this.comparator(); + return cmp.compare(a, b); + } + + boolean rangeContains(@Nullable Object o) { + return !(o == null || this.lowerBound != null && this.compare(this.lowerBound, o) > 0 || this.upperBound != null && this.compare(this.upperBound, o) <= 0); + } + + @Override + public SortedMap subMap(C fromKey, C toKey) { + Preconditions.checkArgument(this.rangeContains(Preconditions.checkNotNull(fromKey)) && this.rangeContains(Preconditions.checkNotNull(toKey))); + return new TreeRow(this.rowKey, fromKey, toKey); + } + + @Override + public SortedMap headMap(C toKey) { + Preconditions.checkArgument(this.rangeContains(Preconditions.checkNotNull(toKey))); + return new TreeRow(this.rowKey, this.lowerBound, toKey); + } + + @Override + public SortedMap tailMap(C fromKey) { + Preconditions.checkArgument(this.rangeContains(Preconditions.checkNotNull(fromKey))); + return new TreeRow(this.rowKey, fromKey, this.upperBound); + } + + @Override + public C firstKey() { + Map backing = this.backingRowMap(); + if (backing == null) { + throw new NoSuchElementException(); + } + return this.backingRowMap().firstKey(); + } + + @Override + public C lastKey() { + Map backing = this.backingRowMap(); + if (backing == null) { + throw new NoSuchElementException(); + } + return this.backingRowMap().lastKey(); + } + + SortedMap wholeRow() { + if (this.wholeRow == null || this.wholeRow.isEmpty() && TreeBasedTable.this.backingMap.containsKey(this.rowKey)) { + this.wholeRow = (SortedMap)TreeBasedTable.this.backingMap.get(this.rowKey); + } + return this.wholeRow; + } + + SortedMap backingRowMap() { + return (SortedMap)super.backingRowMap(); + } + + SortedMap computeBackingRowMap() { + SortedMap map = this.wholeRow(); + if (map != null) { + if (this.lowerBound != null) { + map = map.tailMap(this.lowerBound); + } + if (this.upperBound != null) { + map = map.headMap(this.upperBound); + } + return map; + } + return null; + } + + @Override + void maintainEmptyInvariant() { + if (this.wholeRow() != null && this.wholeRow.isEmpty()) { + TreeBasedTable.this.backingMap.remove(this.rowKey); + this.wholeRow = null; + this.backingRowMap = null; + } + } + + @Override + public boolean containsKey(Object key) { + return this.rangeContains(key) && super.containsKey(key); + } + + @Override + public V put(C key, V value) { + Preconditions.checkArgument(this.rangeContains(Preconditions.checkNotNull(key))); + return super.put(key, value); + } + } + + private static class Factory + implements Supplier>, + Serializable { + final Comparator comparator; + private static final long serialVersionUID = 0L; + + Factory(Comparator comparator) { + this.comparator = comparator; + } + + @Override + public TreeMap get() { + return new TreeMap(this.comparator); + } + } +} diff --git a/src/com/google/common/collect/TreeMultimap.java b/src/com/google/common/collect/TreeMultimap.java new file mode 100644 index 0000000..2cac2b0 --- /dev/null +++ b/src/com/google/common/collect/TreeMultimap.java @@ -0,0 +1,144 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractMapBasedMultimap; +import com.google.common.collect.AbstractSortedKeySortedSetMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Ordering; +import com.google.common.collect.Serialization; +import com.google.common.collect.Sets; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Comparator; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true, emulated=true) +public class TreeMultimap +extends AbstractSortedKeySortedSetMultimap { + private transient Comparator keyComparator; + private transient Comparator valueComparator; + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static TreeMultimap create() { + return new TreeMultimap(Ordering.natural(), Ordering.natural()); + } + + public static TreeMultimap create(Comparator keyComparator, Comparator valueComparator) { + return new TreeMultimap(Preconditions.checkNotNull(keyComparator), Preconditions.checkNotNull(valueComparator)); + } + + public static TreeMultimap create(Multimap multimap) { + return new TreeMultimap(Ordering.natural(), Ordering.natural(), multimap); + } + + TreeMultimap(Comparator keyComparator, Comparator valueComparator) { + super(new TreeMap(keyComparator)); + this.keyComparator = keyComparator; + this.valueComparator = valueComparator; + } + + private TreeMultimap(Comparator keyComparator, Comparator valueComparator, Multimap multimap) { + this(keyComparator, valueComparator); + this.putAll((Multimap)multimap); + } + + @Override + SortedSet createCollection() { + return new TreeSet(this.valueComparator); + } + + @Override + Collection createCollection(@Nullable K key) { + if (key == null) { + this.keyComparator().compare(key, key); + } + return super.createCollection(key); + } + + public Comparator keyComparator() { + return this.keyComparator; + } + + @Override + public Comparator valueComparator() { + return this.valueComparator; + } + + @Override + @GwtIncompatible(value="NavigableMap") + NavigableMap> backingMap() { + return (NavigableMap)super.backingMap(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public NavigableSet get(@Nullable K key) { + return (NavigableSet)super.get((Object)key); + } + + @Override + @GwtIncompatible(value="NavigableSet") + Collection unmodifiableCollectionSubclass(Collection collection) { + return Sets.unmodifiableNavigableSet((NavigableSet)collection); + } + + @Override + @GwtIncompatible(value="NavigableSet") + Collection wrapCollection(K key, Collection collection) { + return new AbstractMapBasedMultimap.WrappedNavigableSet((AbstractMapBasedMultimap)this, key, (NavigableSet)collection, null); + } + + @Override + @GwtIncompatible(value="NavigableSet") + public NavigableSet keySet() { + return (NavigableSet)super.keySet(); + } + + @Override + @GwtIncompatible(value="NavigableSet") + NavigableSet createKeySet() { + return new AbstractMapBasedMultimap.NavigableKeySet((AbstractMapBasedMultimap)this, this.backingMap()); + } + + @Override + @GwtIncompatible(value="NavigableMap") + public NavigableMap> asMap() { + return (NavigableMap)super.asMap(); + } + + @Override + @GwtIncompatible(value="NavigableMap") + NavigableMap> createAsMap() { + return new AbstractMapBasedMultimap.NavigableAsMap((AbstractMapBasedMultimap)this, this.backingMap()); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.keyComparator()); + stream.writeObject(this.valueComparator()); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.keyComparator = Preconditions.checkNotNull((Comparator)stream.readObject()); + this.valueComparator = Preconditions.checkNotNull((Comparator)stream.readObject()); + this.setMap(new TreeMap(this.keyComparator)); + Serialization.populateMultimap(this, stream); + } +} diff --git a/src/com/google/common/collect/TreeMultiset.java b/src/com/google/common/collect/TreeMultiset.java new file mode 100644 index 0000000..8693760 --- /dev/null +++ b/src/com/google/common/collect/TreeMultiset.java @@ -0,0 +1,869 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractSortedMultiset; +import com.google.common.collect.BoundType; +import com.google.common.collect.CollectPreconditions; +import com.google.common.collect.GeneralRange; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Ordering; +import com.google.common.collect.Serialization; +import com.google.common.collect.SortedMultiset; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class TreeMultiset +extends AbstractSortedMultiset +implements Serializable { + private final transient Reference> rootReference; + private final transient GeneralRange range; + private final transient AvlNode header; + @GwtIncompatible(value="not needed in emulated source") + private static final long serialVersionUID = 1L; + + public static TreeMultiset create() { + return new TreeMultiset(Ordering.natural()); + } + + public static TreeMultiset create(@Nullable Comparator comparator) { + return comparator == null ? new TreeMultiset(Ordering.natural()) : new TreeMultiset(comparator); + } + + public static TreeMultiset create(Iterable elements) { + TreeMultiset multiset = TreeMultiset.create(); + Iterables.addAll(multiset, elements); + return multiset; + } + + TreeMultiset(Reference> rootReference, GeneralRange range, AvlNode endLink) { + super(range.comparator()); + this.rootReference = rootReference; + this.range = range; + this.header = endLink; + } + + TreeMultiset(Comparator comparator) { + super(comparator); + this.range = GeneralRange.all(comparator); + this.header = new AvlNode(null, 1); + TreeMultiset.successor(this.header, this.header); + this.rootReference = new Reference(); + } + + private long aggregateForEntries(Aggregate aggr) { + AvlNode root = this.rootReference.get(); + long total = aggr.treeAggregate(root); + if (this.range.hasLowerBound()) { + total -= this.aggregateBelowRange(aggr, root); + } + if (this.range.hasUpperBound()) { + total -= this.aggregateAboveRange(aggr, root); + } + return total; + } + + private long aggregateBelowRange(Aggregate aggr, @Nullable AvlNode node) { + if (node == null) { + return 0L; + } + int cmp = this.comparator().compare(this.range.getLowerEndpoint(), ((AvlNode)node).elem); + if (cmp < 0) { + return this.aggregateBelowRange(aggr, ((AvlNode)node).left); + } + if (cmp == 0) { + switch (this.range.getLowerBoundType()) { + case OPEN: { + return (long)aggr.nodeAggregate(node) + aggr.treeAggregate(((AvlNode)node).left); + } + case CLOSED: { + return aggr.treeAggregate(((AvlNode)node).left); + } + } + throw new AssertionError(); + } + return aggr.treeAggregate(((AvlNode)node).left) + (long)aggr.nodeAggregate(node) + this.aggregateBelowRange(aggr, ((AvlNode)node).right); + } + + private long aggregateAboveRange(Aggregate aggr, @Nullable AvlNode node) { + if (node == null) { + return 0L; + } + int cmp = this.comparator().compare(this.range.getUpperEndpoint(), ((AvlNode)node).elem); + if (cmp > 0) { + return this.aggregateAboveRange(aggr, ((AvlNode)node).right); + } + if (cmp == 0) { + switch (this.range.getUpperBoundType()) { + case OPEN: { + return (long)aggr.nodeAggregate(node) + aggr.treeAggregate(((AvlNode)node).right); + } + case CLOSED: { + return aggr.treeAggregate(((AvlNode)node).right); + } + } + throw new AssertionError(); + } + return aggr.treeAggregate(((AvlNode)node).right) + (long)aggr.nodeAggregate(node) + this.aggregateAboveRange(aggr, ((AvlNode)node).left); + } + + @Override + public int size() { + return Ints.saturatedCast(this.aggregateForEntries(Aggregate.SIZE)); + } + + @Override + int distinctElements() { + return Ints.saturatedCast(this.aggregateForEntries(Aggregate.DISTINCT)); + } + + @Override + public int count(@Nullable Object element) { + try { + Object e = element; + AvlNode root = this.rootReference.get(); + if (!this.range.contains(e) || root == null) { + return 0; + } + return root.count(this.comparator(), e); + } + catch (ClassCastException e) { + return 0; + } + catch (NullPointerException e) { + return 0; + } + } + + @Override + public int add(@Nullable E element, int occurrences) { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return this.count(element); + } + Preconditions.checkArgument(this.range.contains(element)); + AvlNode root = this.rootReference.get(); + if (root == null) { + this.comparator().compare(element, element); + AvlNode newRoot = new AvlNode(element, occurrences); + TreeMultiset.successor(this.header, newRoot, this.header); + this.rootReference.checkAndSet(root, newRoot); + return 0; + } + int[] result = new int[1]; + AvlNode newRoot = root.add(this.comparator(), element, occurrences, result); + this.rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + @Override + public int remove(@Nullable Object element, int occurrences) { + AvlNode newRoot; + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return this.count(element); + } + AvlNode root = this.rootReference.get(); + int[] result = new int[1]; + try { + Object e = element; + if (!this.range.contains(e) || root == null) { + return 0; + } + newRoot = root.remove(this.comparator(), e, occurrences, result); + } + catch (ClassCastException e) { + return 0; + } + catch (NullPointerException e) { + return 0; + } + this.rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + @Override + public int setCount(@Nullable E element, int count) { + CollectPreconditions.checkNonnegative(count, "count"); + if (!this.range.contains(element)) { + Preconditions.checkArgument(count == 0); + return 0; + } + AvlNode root = this.rootReference.get(); + if (root == null) { + if (count > 0) { + this.add(element, count); + } + return 0; + } + int[] result = new int[1]; + AvlNode newRoot = root.setCount(this.comparator(), element, count, result); + this.rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + @Override + public boolean setCount(@Nullable E element, int oldCount, int newCount) { + CollectPreconditions.checkNonnegative(newCount, "newCount"); + CollectPreconditions.checkNonnegative(oldCount, "oldCount"); + Preconditions.checkArgument(this.range.contains(element)); + AvlNode root = this.rootReference.get(); + if (root == null) { + if (oldCount == 0) { + if (newCount > 0) { + this.add(element, newCount); + } + return true; + } + return false; + } + int[] result = new int[1]; + AvlNode newRoot = root.setCount(this.comparator(), element, oldCount, newCount, result); + this.rootReference.checkAndSet(root, newRoot); + return result[0] == oldCount; + } + + private Multiset.Entry wrapEntry(final AvlNode baseEntry) { + return new Multisets.AbstractEntry(){ + + @Override + public E getElement() { + return baseEntry.getElement(); + } + + @Override + public int getCount() { + int result = baseEntry.getCount(); + if (result == 0) { + return TreeMultiset.this.count(this.getElement()); + } + return result; + } + }; + } + + @Nullable + private AvlNode firstNode() { + AvlNode node; + AvlNode root = this.rootReference.get(); + if (root == null) { + return null; + } + if (this.range.hasLowerBound()) { + E endpoint = this.range.getLowerEndpoint(); + node = ((AvlNode)this.rootReference.get()).ceiling(this.comparator(), endpoint); + if (node == null) { + return null; + } + if (this.range.getLowerBoundType() == BoundType.OPEN && this.comparator().compare(endpoint, node.getElement()) == 0) { + node = node.succ; + } + } else { + node = ((AvlNode)this.header).succ; + } + return node == this.header || !this.range.contains(node.getElement()) ? null : node; + } + + @Nullable + private AvlNode lastNode() { + AvlNode node; + AvlNode root = this.rootReference.get(); + if (root == null) { + return null; + } + if (this.range.hasUpperBound()) { + E endpoint = this.range.getUpperEndpoint(); + node = ((AvlNode)this.rootReference.get()).floor(this.comparator(), endpoint); + if (node == null) { + return null; + } + if (this.range.getUpperBoundType() == BoundType.OPEN && this.comparator().compare(endpoint, node.getElement()) == 0) { + node = node.pred; + } + } else { + node = ((AvlNode)this.header).pred; + } + return node == this.header || !this.range.contains(node.getElement()) ? null : node; + } + + @Override + Iterator> entryIterator() { + return new Iterator>(){ + AvlNode current; + Multiset.Entry prevEntry; + { + this.current = TreeMultiset.this.firstNode(); + } + + @Override + public boolean hasNext() { + if (this.current == null) { + return false; + } + if (TreeMultiset.this.range.tooHigh(this.current.getElement())) { + this.current = null; + return false; + } + return true; + } + + @Override + public Multiset.Entry next() { + Multiset.Entry result; + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.prevEntry = result = TreeMultiset.this.wrapEntry(this.current); + this.current = this.current.succ == TreeMultiset.this.header ? null : this.current.succ; + return result; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.prevEntry != null); + TreeMultiset.this.setCount(this.prevEntry.getElement(), 0); + this.prevEntry = null; + } + }; + } + + @Override + Iterator> descendingEntryIterator() { + return new Iterator>(){ + AvlNode current; + Multiset.Entry prevEntry; + { + this.current = TreeMultiset.this.lastNode(); + this.prevEntry = null; + } + + @Override + public boolean hasNext() { + if (this.current == null) { + return false; + } + if (TreeMultiset.this.range.tooLow(this.current.getElement())) { + this.current = null; + return false; + } + return true; + } + + @Override + public Multiset.Entry next() { + Multiset.Entry result; + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + this.prevEntry = result = TreeMultiset.this.wrapEntry(this.current); + this.current = this.current.pred == TreeMultiset.this.header ? null : this.current.pred; + return result; + } + + @Override + public void remove() { + CollectPreconditions.checkRemove(this.prevEntry != null); + TreeMultiset.this.setCount(this.prevEntry.getElement(), 0); + this.prevEntry = null; + } + }; + } + + @Override + public SortedMultiset headMultiset(@Nullable E upperBound, BoundType boundType) { + return new TreeMultiset(this.rootReference, this.range.intersect(GeneralRange.upTo(this.comparator(), upperBound, boundType)), this.header); + } + + @Override + public SortedMultiset tailMultiset(@Nullable E lowerBound, BoundType boundType) { + return new TreeMultiset(this.rootReference, this.range.intersect(GeneralRange.downTo(this.comparator(), lowerBound, boundType)), this.header); + } + + static int distinctElements(@Nullable AvlNode node) { + return node == null ? 0 : ((AvlNode)node).distinctElements; + } + + private static void successor(AvlNode a, AvlNode b) { + ((AvlNode)a).succ = (AvlNode)b; + ((AvlNode)b).pred = (AvlNode)a; + } + + private static void successor(AvlNode a, AvlNode b, AvlNode c) { + TreeMultiset.successor(a, b); + TreeMultiset.successor(b, c); + } + + @GwtIncompatible(value="java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(this.elementSet().comparator()); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible(value="java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + Comparator comparator = (Comparator)stream.readObject(); + Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set((AbstractSortedMultiset)this, comparator); + Serialization.getFieldSetter(TreeMultiset.class, "range").set(this, GeneralRange.all(comparator)); + Serialization.getFieldSetter(TreeMultiset.class, "rootReference").set(this, new Reference()); + AvlNode header = new AvlNode(null, 1); + Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header); + TreeMultiset.successor(header, header); + Serialization.populateMultiset(this, stream); + } + + private static final class AvlNode + extends Multisets.AbstractEntry { + @Nullable + private final E elem; + private int elemCount; + private int distinctElements; + private long totalCount; + private int height; + private AvlNode left; + private AvlNode right; + private AvlNode pred; + private AvlNode succ; + + AvlNode(@Nullable E elem, int elemCount) { + Preconditions.checkArgument(elemCount > 0); + this.elem = elem; + this.elemCount = elemCount; + this.totalCount = elemCount; + this.distinctElements = 1; + this.height = 1; + this.left = null; + this.right = null; + } + + public int count(Comparator comparator, E e) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + return this.left == null ? 0 : this.left.count(comparator, e); + } + if (cmp > 0) { + return this.right == null ? 0 : this.right.count(comparator, e); + } + return this.elemCount; + } + + private AvlNode addRightChild(E e, int count) { + this.right = new AvlNode(e, count); + TreeMultiset.successor(this, this.right, this.succ); + this.height = Math.max(2, this.height); + ++this.distinctElements; + this.totalCount += (long)count; + return this; + } + + private AvlNode addLeftChild(E e, int count) { + this.left = new AvlNode(e, count); + TreeMultiset.successor(this.pred, this.left, this); + this.height = Math.max(2, this.height); + ++this.distinctElements; + this.totalCount += (long)count; + return this; + } + + AvlNode add(Comparator comparator, @Nullable E e, int count, int[] result) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + AvlNode initLeft = this.left; + if (initLeft == null) { + result[0] = 0; + return this.addLeftChild(e, count); + } + int initHeight = initLeft.height; + this.left = initLeft.add(comparator, e, count, result); + if (result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)count; + return this.left.height == initHeight ? this : this.rebalance(); + } + if (cmp > 0) { + AvlNode initRight = this.right; + if (initRight == null) { + result[0] = 0; + return this.addRightChild(e, count); + } + int initHeight = initRight.height; + this.right = initRight.add(comparator, e, count, result); + if (result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)count; + return this.right.height == initHeight ? this : super.rebalance(); + } + result[0] = this.elemCount; + long resultCount = (long)this.elemCount + (long)count; + Preconditions.checkArgument(resultCount <= Integer.MAX_VALUE); + this.elemCount += count; + this.totalCount += (long)count; + return this; + } + + AvlNode remove(Comparator comparator, @Nullable E e, int count, int[] result) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + AvlNode initLeft = this.left; + if (initLeft == null) { + result[0] = 0; + return this; + } + this.left = initLeft.remove(comparator, e, count, result); + if (result[0] > 0) { + if (count >= result[0]) { + --this.distinctElements; + this.totalCount -= (long)result[0]; + } else { + this.totalCount -= (long)count; + } + } + return result[0] == 0 ? this : this.rebalance(); + } + if (cmp > 0) { + AvlNode initRight = this.right; + if (initRight == null) { + result[0] = 0; + return this; + } + this.right = initRight.remove(comparator, e, count, result); + if (result[0] > 0) { + if (count >= result[0]) { + --this.distinctElements; + this.totalCount -= (long)result[0]; + } else { + this.totalCount -= (long)count; + } + } + return this.rebalance(); + } + result[0] = this.elemCount; + if (count >= this.elemCount) { + return this.deleteMe(); + } + this.elemCount -= count; + this.totalCount -= (long)count; + return this; + } + + AvlNode setCount(Comparator comparator, @Nullable E e, int count, int[] result) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + AvlNode initLeft = this.left; + if (initLeft == null) { + result[0] = 0; + return count > 0 ? this.addLeftChild(e, count) : this; + } + this.left = initLeft.setCount(comparator, e, count, result); + if (count == 0 && result[0] != 0) { + --this.distinctElements; + } else if (count > 0 && result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)(count - result[0]); + return super.rebalance(); + } + if (cmp > 0) { + AvlNode initRight = this.right; + if (initRight == null) { + result[0] = 0; + return count > 0 ? super.addRightChild(e, count) : this; + } + this.right = initRight.setCount(comparator, e, count, result); + if (count == 0 && result[0] != 0) { + --this.distinctElements; + } else if (count > 0 && result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)(count - result[0]); + return super.rebalance(); + } + result[0] = this.elemCount; + if (count == 0) { + return this.deleteMe(); + } + this.totalCount += (long)(count - this.elemCount); + this.elemCount = count; + return this; + } + + AvlNode setCount(Comparator comparator, @Nullable E e, int expectedCount, int newCount, int[] result) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + AvlNode initLeft = this.left; + if (initLeft == null) { + result[0] = 0; + if (expectedCount == 0 && newCount > 0) { + return this.addLeftChild(e, newCount); + } + return this; + } + this.left = initLeft.setCount(comparator, e, expectedCount, newCount, result); + if (result[0] == expectedCount) { + if (newCount == 0 && result[0] != 0) { + --this.distinctElements; + } else if (newCount > 0 && result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)(newCount - result[0]); + } + return this.rebalance(); + } + if (cmp > 0) { + AvlNode initRight = this.right; + if (initRight == null) { + result[0] = 0; + if (expectedCount == 0 && newCount > 0) { + return this.addRightChild(e, newCount); + } + return this; + } + this.right = initRight.setCount(comparator, e, expectedCount, newCount, result); + if (result[0] == expectedCount) { + if (newCount == 0 && result[0] != 0) { + --this.distinctElements; + } else if (newCount > 0 && result[0] == 0) { + ++this.distinctElements; + } + this.totalCount += (long)(newCount - result[0]); + } + return this.rebalance(); + } + result[0] = this.elemCount; + if (expectedCount == this.elemCount) { + if (newCount == 0) { + return this.deleteMe(); + } + this.totalCount += (long)(newCount - this.elemCount); + this.elemCount = newCount; + } + return this; + } + + private AvlNode deleteMe() { + int oldElemCount = this.elemCount; + this.elemCount = 0; + TreeMultiset.successor(this.pred, this.succ); + if (this.left == null) { + return this.right; + } + if (this.right == null) { + return this.left; + } + if (this.left.height >= this.right.height) { + AvlNode newTop = this.pred; + newTop.left = super.removeMax(newTop); + newTop.right = this.right; + newTop.distinctElements = this.distinctElements - 1; + newTop.totalCount = this.totalCount - (long)oldElemCount; + return super.rebalance(); + } + AvlNode newTop = this.succ; + newTop.right = super.removeMin(newTop); + newTop.left = this.left; + newTop.distinctElements = this.distinctElements - 1; + newTop.totalCount = this.totalCount - (long)oldElemCount; + return super.rebalance(); + } + + private AvlNode removeMin(AvlNode node) { + if (this.left == null) { + return this.right; + } + this.left = super.removeMin(node); + --this.distinctElements; + this.totalCount -= (long)node.elemCount; + return this.rebalance(); + } + + private AvlNode removeMax(AvlNode node) { + if (this.right == null) { + return this.left; + } + this.right = super.removeMax(node); + --this.distinctElements; + this.totalCount -= (long)node.elemCount; + return this.rebalance(); + } + + private void recomputeMultiset() { + this.distinctElements = 1 + TreeMultiset.distinctElements(this.left) + TreeMultiset.distinctElements(this.right); + this.totalCount = (long)this.elemCount + AvlNode.totalCount(this.left) + AvlNode.totalCount(this.right); + } + + private void recomputeHeight() { + this.height = 1 + Math.max(AvlNode.height(this.left), AvlNode.height(this.right)); + } + + private void recompute() { + this.recomputeMultiset(); + this.recomputeHeight(); + } + + private AvlNode rebalance() { + switch (this.balanceFactor()) { + case -2: { + if (super.balanceFactor() > 0) { + this.right = super.rotateRight(); + } + return this.rotateLeft(); + } + case 2: { + if (super.balanceFactor() < 0) { + this.left = super.rotateLeft(); + } + return this.rotateRight(); + } + } + this.recomputeHeight(); + return this; + } + + private int balanceFactor() { + return AvlNode.height(this.left) - AvlNode.height(this.right); + } + + private AvlNode rotateLeft() { + Preconditions.checkState(this.right != null); + AvlNode newTop = this.right; + this.right = newTop.left; + newTop.left = this; + newTop.totalCount = this.totalCount; + newTop.distinctElements = this.distinctElements; + this.recompute(); + super.recomputeHeight(); + return newTop; + } + + private AvlNode rotateRight() { + Preconditions.checkState(this.left != null); + AvlNode newTop = this.left; + this.left = newTop.right; + newTop.right = this; + newTop.totalCount = this.totalCount; + newTop.distinctElements = this.distinctElements; + this.recompute(); + super.recomputeHeight(); + return newTop; + } + + private static long totalCount(@Nullable AvlNode node) { + return node == null ? 0L : node.totalCount; + } + + private static int height(@Nullable AvlNode node) { + return node == null ? 0 : node.height; + } + + @Nullable + private AvlNode ceiling(Comparator comparator, E e) { + int cmp = comparator.compare(e, this.elem); + if (cmp < 0) { + return this.left == null ? this : MoreObjects.firstNonNull(super.ceiling(comparator, e), this); + } + if (cmp == 0) { + return this; + } + return this.right == null ? null : super.ceiling(comparator, e); + } + + @Nullable + private AvlNode floor(Comparator comparator, E e) { + int cmp = comparator.compare(e, this.elem); + if (cmp > 0) { + return this.right == null ? this : MoreObjects.firstNonNull(super.floor(comparator, e), this); + } + if (cmp == 0) { + return this; + } + return this.left == null ? null : super.floor(comparator, e); + } + + @Override + public E getElement() { + return this.elem; + } + + @Override + public int getCount() { + return this.elemCount; + } + + @Override + public String toString() { + return Multisets.immutableEntry(this.getElement(), this.getCount()).toString(); + } + } + + private static final class Reference { + @Nullable + private T value; + + private Reference() { + } + + @Nullable + public T get() { + return this.value; + } + + public void checkAndSet(@Nullable T expected, T newValue) { + if (this.value != expected) { + throw new ConcurrentModificationException(); + } + this.value = newValue; + } + } + + private static enum Aggregate { + SIZE{ + + @Override + int nodeAggregate(AvlNode node) { + return ((AvlNode)node).elemCount; + } + + @Override + long treeAggregate(@Nullable AvlNode root) { + return root == null ? 0L : ((AvlNode)root).totalCount; + } + } + , + DISTINCT{ + + @Override + int nodeAggregate(AvlNode node) { + return 1; + } + + @Override + long treeAggregate(@Nullable AvlNode root) { + return root == null ? 0L : (long)((AvlNode)root).distinctElements; + } + }; + + + abstract int nodeAggregate(AvlNode var1); + + abstract long treeAggregate(@Nullable AvlNode var1); + } +} diff --git a/src/com/google/common/collect/TreeRangeMap.java b/src/com/google/common/collect/TreeRangeMap.java new file mode 100644 index 0000000..11780ce --- /dev/null +++ b/src/com/google/common/collect/TreeRangeMap.java @@ -0,0 +1,526 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.Cut; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Range; +import com.google.common.collect.RangeMap; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +@GwtIncompatible(value="NavigableMap") +public final class TreeRangeMap +implements RangeMap { + private final NavigableMap, RangeMapEntry> entriesByLowerBound = Maps.newTreeMap(); + private static final RangeMap EMPTY_SUB_RANGE_MAP = new RangeMap(){ + + @Nullable + public Object get(Comparable key) { + return null; + } + + @Nullable + public Map.Entry getEntry(Comparable key) { + return null; + } + + public Range span() { + throw new NoSuchElementException(); + } + + public void put(Range range, Object value) { + Preconditions.checkNotNull(range); + String string = String.valueOf(String.valueOf(range)); + throw new IllegalArgumentException(new StringBuilder(46 + string.length()).append("Cannot insert range ").append(string).append(" into an empty subRangeMap").toString()); + } + + public void putAll(RangeMap rangeMap) { + if (!rangeMap.asMapOfRanges().isEmpty()) { + throw new IllegalArgumentException("Cannot putAll(nonEmptyRangeMap) into an empty subRangeMap"); + } + } + + @Override + public void clear() { + } + + public void remove(Range range) { + Preconditions.checkNotNull(range); + } + + public Map asMapOfRanges() { + return Collections.emptyMap(); + } + + public RangeMap subRangeMap(Range range) { + Preconditions.checkNotNull(range); + return this; + } + }; + + public static TreeRangeMap create() { + return new TreeRangeMap(); + } + + private TreeRangeMap() { + } + + @Override + @Nullable + public V get(K key) { + Map.Entry, V> entry = this.getEntry(key); + return entry == null ? null : (V)entry.getValue(); + } + + @Override + @Nullable + public Map.Entry, V> getEntry(K key) { + Map.Entry, RangeMapEntry> mapEntry = this.entriesByLowerBound.floorEntry(Cut.belowValue(key)); + if (mapEntry != null && mapEntry.getValue().contains(key)) { + return mapEntry.getValue(); + } + return null; + } + + @Override + public void put(Range range, V value) { + if (!range.isEmpty()) { + Preconditions.checkNotNull(value); + this.remove(range); + this.entriesByLowerBound.put(range.lowerBound, new RangeMapEntry(range, value)); + } + } + + @Override + public void putAll(RangeMap rangeMap) { + for (Map.Entry, V> entry : rangeMap.asMapOfRanges().entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void clear() { + this.entriesByLowerBound.clear(); + } + + @Override + public Range span() { + Map.Entry, RangeMapEntry> firstEntry = this.entriesByLowerBound.firstEntry(); + Map.Entry, RangeMapEntry> lastEntry = this.entriesByLowerBound.lastEntry(); + if (firstEntry == null) { + throw new NoSuchElementException(); + } + return Range.create(((Range)firstEntry.getValue().getKey()).lowerBound, ((Range)lastEntry.getValue().getKey()).upperBound); + } + + private void putRangeMapEntry(Cut lowerBound, Cut upperBound, V value) { + this.entriesByLowerBound.put(lowerBound, new RangeMapEntry(lowerBound, upperBound, value)); + } + + @Override + public void remove(Range rangeToRemove) { + RangeMapEntry rangeMapEntry; + Map.Entry mapEntryAboveToTruncate; + RangeMapEntry rangeMapEntry2; + if (rangeToRemove.isEmpty()) { + return; + } + Map.Entry mapEntryBelowToTruncate = this.entriesByLowerBound.lowerEntry(rangeToRemove.lowerBound); + if (mapEntryBelowToTruncate != null && (rangeMapEntry2 = mapEntryBelowToTruncate.getValue()).getUpperBound().compareTo(rangeToRemove.lowerBound) > 0) { + if (rangeMapEntry2.getUpperBound().compareTo(rangeToRemove.upperBound) > 0) { + this.putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry2.getUpperBound(), mapEntryBelowToTruncate.getValue().getValue()); + } + this.putRangeMapEntry(rangeMapEntry2.getLowerBound(), rangeToRemove.lowerBound, mapEntryBelowToTruncate.getValue().getValue()); + } + if ((mapEntryAboveToTruncate = this.entriesByLowerBound.lowerEntry(rangeToRemove.upperBound)) != null && (rangeMapEntry = mapEntryAboveToTruncate.getValue()).getUpperBound().compareTo(rangeToRemove.upperBound) > 0) { + this.putRangeMapEntry(rangeToRemove.upperBound, rangeMapEntry.getUpperBound(), mapEntryAboveToTruncate.getValue().getValue()); + this.entriesByLowerBound.remove(rangeToRemove.lowerBound); + } + this.entriesByLowerBound.subMap(rangeToRemove.lowerBound, rangeToRemove.upperBound).clear(); + } + + @Override + public Map, V> asMapOfRanges() { + return new AsMapOfRanges(); + } + + @Override + public RangeMap subRangeMap(Range subRange) { + if (subRange.equals(Range.all())) { + return this; + } + return new SubRangeMap(subRange); + } + + private RangeMap emptySubRangeMap() { + return EMPTY_SUB_RANGE_MAP; + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof RangeMap) { + RangeMap rangeMap = (RangeMap)o; + return this.asMapOfRanges().equals(rangeMap.asMapOfRanges()); + } + return false; + } + + @Override + public int hashCode() { + return this.asMapOfRanges().hashCode(); + } + + @Override + public String toString() { + return this.entriesByLowerBound.values().toString(); + } + + private class SubRangeMap + implements RangeMap { + private final Range subRange; + + SubRangeMap(Range subRange) { + this.subRange = subRange; + } + + @Override + @Nullable + public V get(K key) { + return this.subRange.contains(key) ? (Object)TreeRangeMap.this.get(key) : null; + } + + @Override + @Nullable + public Map.Entry, V> getEntry(K key) { + Map.Entry entry; + if (this.subRange.contains(key) && (entry = TreeRangeMap.this.getEntry(key)) != null) { + return Maps.immutableEntry(entry.getKey().intersection(this.subRange), entry.getValue()); + } + return null; + } + + @Override + public Range span() { + Cut lowerBound; + Map.Entry lowerEntry = TreeRangeMap.this.entriesByLowerBound.floorEntry(this.subRange.lowerBound); + if (lowerEntry != null && ((RangeMapEntry)lowerEntry.getValue()).getUpperBound().compareTo(this.subRange.lowerBound) > 0) { + lowerBound = this.subRange.lowerBound; + } else { + lowerBound = TreeRangeMap.this.entriesByLowerBound.ceilingKey(this.subRange.lowerBound); + if (lowerBound == null || lowerBound.compareTo(this.subRange.upperBound) >= 0) { + throw new NoSuchElementException(); + } + } + Map.Entry upperEntry = TreeRangeMap.this.entriesByLowerBound.lowerEntry(this.subRange.upperBound); + if (upperEntry == null) { + throw new NoSuchElementException(); + } + Cut upperBound = ((RangeMapEntry)upperEntry.getValue()).getUpperBound().compareTo(this.subRange.upperBound) >= 0 ? this.subRange.upperBound : ((RangeMapEntry)upperEntry.getValue()).getUpperBound(); + return Range.create(lowerBound, upperBound); + } + + @Override + public void put(Range range, V value) { + Preconditions.checkArgument(this.subRange.encloses(range), "Cannot put range %s into a subRangeMap(%s)", range, this.subRange); + TreeRangeMap.this.put(range, value); + } + + @Override + public void putAll(RangeMap rangeMap) { + if (rangeMap.asMapOfRanges().isEmpty()) { + return; + } + Range span = rangeMap.span(); + Preconditions.checkArgument(this.subRange.encloses(span), "Cannot putAll rangeMap with span %s into a subRangeMap(%s)", span, this.subRange); + TreeRangeMap.this.putAll(rangeMap); + } + + @Override + public void clear() { + TreeRangeMap.this.remove(this.subRange); + } + + @Override + public void remove(Range range) { + if (range.isConnected(this.subRange)) { + TreeRangeMap.this.remove(range.intersection(this.subRange)); + } + } + + @Override + public RangeMap subRangeMap(Range range) { + if (!range.isConnected(this.subRange)) { + return TreeRangeMap.this.emptySubRangeMap(); + } + return TreeRangeMap.this.subRangeMap(range.intersection(this.subRange)); + } + + @Override + public Map, V> asMapOfRanges() { + return new SubRangeMapAsMap(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof RangeMap) { + RangeMap rangeMap = (RangeMap)o; + return this.asMapOfRanges().equals(rangeMap.asMapOfRanges()); + } + return false; + } + + @Override + public int hashCode() { + return this.asMapOfRanges().hashCode(); + } + + @Override + public String toString() { + return this.asMapOfRanges().toString(); + } + + class SubRangeMapAsMap + extends AbstractMap, V> { + SubRangeMapAsMap() { + } + + @Override + public boolean containsKey(Object key) { + return this.get(key) != null; + } + + @Override + public V get(Object key) { + try { + if (key instanceof Range) { + Range r = (Range)key; + if (!SubRangeMap.this.subRange.encloses(r) || r.isEmpty()) { + return null; + } + RangeMapEntry candidate = null; + if (r.lowerBound.compareTo(((SubRangeMap)SubRangeMap.this).subRange.lowerBound) == 0) { + Map.Entry entry = TreeRangeMap.this.entriesByLowerBound.floorEntry(r.lowerBound); + if (entry != null) { + candidate = (RangeMapEntry)entry.getValue(); + } + } else { + candidate = (RangeMapEntry)TreeRangeMap.this.entriesByLowerBound.get(r.lowerBound); + } + if (candidate != null && ((Range)candidate.getKey()).isConnected(SubRangeMap.this.subRange) && ((Range)candidate.getKey()).intersection(SubRangeMap.this.subRange).equals(r)) { + return candidate.getValue(); + } + } + } + catch (ClassCastException e) { + return null; + } + return null; + } + + @Override + public V remove(Object key) { + Object value = this.get(key); + if (value != null) { + Range range = (Range)key; + TreeRangeMap.this.remove(range); + return value; + } + return null; + } + + @Override + public void clear() { + SubRangeMap.this.clear(); + } + + private boolean removeEntryIf(Predicate, V>> predicate) { + ArrayList toRemove = Lists.newArrayList(); + for (Map.Entry entry : this.entrySet()) { + if (!predicate.apply(entry)) continue; + toRemove.add(entry.getKey()); + } + for (Range range : toRemove) { + TreeRangeMap.this.remove(range); + } + return !toRemove.isEmpty(); + } + + @Override + public Set> keySet() { + return new Maps.KeySet, V>(this){ + + @Override + public boolean remove(@Nullable Object o) { + return SubRangeMapAsMap.this.remove(o) != null; + } + + @Override + public boolean retainAll(Collection c) { + return SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.not(Predicates.in(c)), Maps.keyFunction())); + } + }; + } + + @Override + public Set, V>> entrySet() { + return new Maps.EntrySet, V>(){ + + @Override + Map, V> map() { + return SubRangeMapAsMap.this; + } + + @Override + public Iterator, V>> iterator() { + if (SubRangeMap.this.subRange.isEmpty()) { + return Iterators.emptyIterator(); + } + Cut cutToStart = MoreObjects.firstNonNull(TreeRangeMap.this.entriesByLowerBound.floorKey(((SubRangeMap)SubRangeMap.this).subRange.lowerBound), ((SubRangeMap)SubRangeMap.this).subRange.lowerBound); + final Iterator backingItr = TreeRangeMap.this.entriesByLowerBound.tailMap(cutToStart, true).values().iterator(); + return new AbstractIterator, V>>(){ + + @Override + protected Map.Entry, V> computeNext() { + RangeMapEntry entry; + while (backingItr.hasNext() && (entry = (RangeMapEntry)backingItr.next()).getLowerBound().compareTo(((SubRangeMap)SubRangeMap.this).subRange.upperBound) < 0) { + if (entry.getUpperBound().compareTo(((SubRangeMap)SubRangeMap.this).subRange.lowerBound) <= 0) continue; + return Maps.immutableEntry(((Range)entry.getKey()).intersection(SubRangeMap.this.subRange), entry.getValue()); + } + return (Map.Entry)this.endOfData(); + } + }; + } + + @Override + public boolean retainAll(Collection c) { + return SubRangeMapAsMap.this.removeEntryIf(Predicates.not(Predicates.in(c))); + } + + @Override + public int size() { + return Iterators.size(this.iterator()); + } + + @Override + public boolean isEmpty() { + return !this.iterator().hasNext(); + } + }; + } + + @Override + public Collection values() { + return new Maps.Values, V>(this){ + + @Override + public boolean removeAll(Collection c) { + return SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.in(c), Maps.valueFunction())); + } + + @Override + public boolean retainAll(Collection c) { + return SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.not(Predicates.in(c)), Maps.valueFunction())); + } + }; + } + } + } + + private final class AsMapOfRanges + extends AbstractMap, V> { + private AsMapOfRanges() { + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.get(key) != null; + } + + @Override + public V get(@Nullable Object key) { + if (key instanceof Range) { + Range range = (Range)key; + RangeMapEntry rangeMapEntry = (RangeMapEntry)TreeRangeMap.this.entriesByLowerBound.get(range.lowerBound); + if (rangeMapEntry != null && ((Range)rangeMapEntry.getKey()).equals(range)) { + return rangeMapEntry.getValue(); + } + } + return null; + } + + @Override + public Set, V>> entrySet() { + return new AbstractSet, V>>(){ + + @Override + public Iterator, V>> iterator() { + return TreeRangeMap.this.entriesByLowerBound.values().iterator(); + } + + @Override + public int size() { + return TreeRangeMap.this.entriesByLowerBound.size(); + } + }; + } + } + + private static final class RangeMapEntry + extends AbstractMapEntry, V> { + private final Range range; + private final V value; + + RangeMapEntry(Cut lowerBound, Cut upperBound, V value) { + this(Range.create(lowerBound, upperBound), value); + } + + RangeMapEntry(Range range, V value) { + this.range = range; + this.value = value; + } + + @Override + public Range getKey() { + return this.range; + } + + @Override + public V getValue() { + return this.value; + } + + public boolean contains(K value) { + return this.range.contains(value); + } + + Cut getLowerBound() { + return this.range.lowerBound; + } + + Cut getUpperBound() { + return this.range.upperBound; + } + } +} diff --git a/src/com/google/common/collect/TreeRangeSet.java b/src/com/google/common/collect/TreeRangeSet.java new file mode 100644 index 0000000..36399d9 --- /dev/null +++ b/src/com/google/common/collect/TreeRangeSet.java @@ -0,0 +1,694 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.AbstractNavigableMap; +import com.google.common.collect.AbstractRangeSet; +import com.google.common.collect.BoundType; +import com.google.common.collect.Cut; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ImmutableRangeSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.TreeMap; +import javax.annotation.Nullable; + +@Beta +@GwtIncompatible(value="uses NavigableMap") +public class TreeRangeSet> +extends AbstractRangeSet { + @VisibleForTesting + final NavigableMap, Range> rangesByLowerBound; + private transient Set> asRanges; + private transient RangeSet complement; + + public static > TreeRangeSet create() { + return new TreeRangeSet(new TreeMap, Range>()); + } + + public static > TreeRangeSet create(RangeSet rangeSet) { + TreeRangeSet result = TreeRangeSet.create(); + result.addAll((RangeSet)rangeSet); + return result; + } + + private TreeRangeSet(NavigableMap, Range> rangesByLowerCut) { + this.rangesByLowerBound = rangesByLowerCut; + } + + @Override + public Set> asRanges() { + AsRanges result = this.asRanges; + return result == null ? (this.asRanges = new AsRanges()) : result; + } + + @Override + @Nullable + public Range rangeContaining(C value) { + Preconditions.checkNotNull(value); + Map.Entry, Range> floorEntry = this.rangesByLowerBound.floorEntry(Cut.belowValue(value)); + if (floorEntry != null && floorEntry.getValue().contains(value)) { + return floorEntry.getValue(); + } + return null; + } + + @Override + public boolean encloses(Range range) { + Preconditions.checkNotNull(range); + Map.Entry floorEntry = this.rangesByLowerBound.floorEntry(range.lowerBound); + return floorEntry != null && floorEntry.getValue().encloses(range); + } + + @Nullable + private Range rangeEnclosing(Range range) { + Preconditions.checkNotNull(range); + Map.Entry floorEntry = this.rangesByLowerBound.floorEntry(range.lowerBound); + return floorEntry != null && floorEntry.getValue().encloses(range) ? floorEntry.getValue() : null; + } + + @Override + public Range span() { + Map.Entry, Range> firstEntry = this.rangesByLowerBound.firstEntry(); + Map.Entry, Range> lastEntry = this.rangesByLowerBound.lastEntry(); + if (firstEntry == null) { + throw new NoSuchElementException(); + } + return Range.create(firstEntry.getValue().lowerBound, lastEntry.getValue().upperBound); + } + + @Override + public void add(Range rangeToAdd) { + Map.Entry entryBelowUB; + Preconditions.checkNotNull(rangeToAdd); + if (rangeToAdd.isEmpty()) { + return; + } + Cut lbToAdd = rangeToAdd.lowerBound; + Cut ubToAdd = rangeToAdd.upperBound; + Map.Entry entryBelowLB = this.rangesByLowerBound.lowerEntry(lbToAdd); + if (entryBelowLB != null) { + Range rangeBelowLB = entryBelowLB.getValue(); + if (rangeBelowLB.upperBound.compareTo(lbToAdd) >= 0) { + if (rangeBelowLB.upperBound.compareTo(ubToAdd) >= 0) { + ubToAdd = rangeBelowLB.upperBound; + } + lbToAdd = rangeBelowLB.lowerBound; + } + } + if ((entryBelowUB = this.rangesByLowerBound.floorEntry(ubToAdd)) != null) { + Range rangeBelowUB = entryBelowUB.getValue(); + if (rangeBelowUB.upperBound.compareTo(ubToAdd) >= 0) { + ubToAdd = rangeBelowUB.upperBound; + } + } + this.rangesByLowerBound.subMap(lbToAdd, ubToAdd).clear(); + this.replaceRangeWithSameLowerBound(Range.create(lbToAdd, ubToAdd)); + } + + @Override + public void remove(Range rangeToRemove) { + Map.Entry entryBelowUB; + Preconditions.checkNotNull(rangeToRemove); + if (rangeToRemove.isEmpty()) { + return; + } + Map.Entry entryBelowLB = this.rangesByLowerBound.lowerEntry(rangeToRemove.lowerBound); + if (entryBelowLB != null) { + Range rangeBelowLB = entryBelowLB.getValue(); + if (rangeBelowLB.upperBound.compareTo(rangeToRemove.lowerBound) >= 0) { + if (rangeToRemove.hasUpperBound() && rangeBelowLB.upperBound.compareTo(rangeToRemove.upperBound) >= 0) { + this.replaceRangeWithSameLowerBound(Range.create(rangeToRemove.upperBound, rangeBelowLB.upperBound)); + } + this.replaceRangeWithSameLowerBound(Range.create(rangeBelowLB.lowerBound, rangeToRemove.lowerBound)); + } + } + if ((entryBelowUB = this.rangesByLowerBound.floorEntry(rangeToRemove.upperBound)) != null) { + Range rangeBelowUB = entryBelowUB.getValue(); + if (rangeToRemove.hasUpperBound() && rangeBelowUB.upperBound.compareTo(rangeToRemove.upperBound) >= 0) { + this.replaceRangeWithSameLowerBound(Range.create(rangeToRemove.upperBound, rangeBelowUB.upperBound)); + } + } + this.rangesByLowerBound.subMap(rangeToRemove.lowerBound, rangeToRemove.upperBound).clear(); + } + + private void replaceRangeWithSameLowerBound(Range range) { + if (range.isEmpty()) { + this.rangesByLowerBound.remove(range.lowerBound); + } else { + this.rangesByLowerBound.put(range.lowerBound, range); + } + } + + @Override + public RangeSet complement() { + Complement result = this.complement; + return result == null ? (this.complement = new Complement()) : result; + } + + @Override + public RangeSet subRangeSet(Range view) { + return view.equals(Range.all()) ? this : new SubRangeSet(view); + } + + private final class SubRangeSet + extends TreeRangeSet { + private final Range restriction; + + SubRangeSet(Range restriction) { + super(new SubRangeSetRangesByLowerBound(Range.all(), restriction, TreeRangeSet.this.rangesByLowerBound)); + this.restriction = restriction; + } + + @Override + public boolean encloses(Range range) { + if (!this.restriction.isEmpty() && this.restriction.encloses(range)) { + Range enclosing = TreeRangeSet.this.rangeEnclosing(range); + return enclosing != null && !enclosing.intersection(this.restriction).isEmpty(); + } + return false; + } + + @Override + @Nullable + public Range rangeContaining(C value) { + if (!this.restriction.contains(value)) { + return null; + } + Range result = TreeRangeSet.this.rangeContaining(value); + return result == null ? null : result.intersection(this.restriction); + } + + @Override + public void add(Range rangeToAdd) { + Preconditions.checkArgument(this.restriction.encloses(rangeToAdd), "Cannot add range %s to subRangeSet(%s)", rangeToAdd, this.restriction); + super.add(rangeToAdd); + } + + @Override + public void remove(Range rangeToRemove) { + if (rangeToRemove.isConnected(this.restriction)) { + TreeRangeSet.this.remove(rangeToRemove.intersection(this.restriction)); + } + } + + @Override + public boolean contains(C value) { + return this.restriction.contains(value) && TreeRangeSet.this.contains((Comparable)value); + } + + @Override + public void clear() { + TreeRangeSet.this.remove(this.restriction); + } + + @Override + public RangeSet subRangeSet(Range view) { + if (view.encloses(this.restriction)) { + return this; + } + if (view.isConnected(this.restriction)) { + return new SubRangeSet(this.restriction.intersection(view)); + } + return ImmutableRangeSet.of(); + } + } + + private static final class SubRangeSetRangesByLowerBound> + extends AbstractNavigableMap, Range> { + private final Range> lowerBoundWindow; + private final Range restriction; + private final NavigableMap, Range> rangesByLowerBound; + private final NavigableMap, Range> rangesByUpperBound; + + private SubRangeSetRangesByLowerBound(Range> lowerBoundWindow, Range restriction, NavigableMap, Range> rangesByLowerBound) { + this.lowerBoundWindow = Preconditions.checkNotNull(lowerBoundWindow); + this.restriction = Preconditions.checkNotNull(restriction); + this.rangesByLowerBound = Preconditions.checkNotNull(rangesByLowerBound); + this.rangesByUpperBound = new RangesByUpperBound(rangesByLowerBound); + } + + private NavigableMap, Range> subMap(Range> window) { + if (!window.isConnected(this.lowerBoundWindow)) { + return ImmutableSortedMap.of(); + } + return new SubRangeSetRangesByLowerBound(this.lowerBoundWindow.intersection(window), this.restriction, this.rangesByLowerBound); + } + + @Override + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) { + return this.subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + @Override + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) { + return this.subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + @Override + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) { + return this.subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + @Override + public Comparator> comparator() { + return Ordering.natural(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.get(key) != null; + } + + @Override + @Nullable + public Range get(@Nullable Object key) { + if (key instanceof Cut) { + try { + Cut cut = (Cut)key; + if (!this.lowerBoundWindow.contains(cut) || cut.compareTo(this.restriction.lowerBound) < 0 || cut.compareTo(this.restriction.upperBound) >= 0) { + return null; + } + if (cut.equals(this.restriction.lowerBound)) { + Range candidate = Maps.valueOrNull(this.rangesByLowerBound.floorEntry(cut)); + if (candidate != null && candidate.upperBound.compareTo(this.restriction.lowerBound) > 0) { + return candidate.intersection(this.restriction); + } + } else { + Range result = (Range)this.rangesByLowerBound.get(cut); + if (result != null) { + return result.intersection(this.restriction); + } + } + } + catch (ClassCastException e) { + return null; + } + } + return null; + } + + @Override + Iterator, Range>> entryIterator() { + if (this.restriction.isEmpty()) { + return Iterators.emptyIterator(); + } + if (this.lowerBoundWindow.upperBound.isLessThan(this.restriction.lowerBound)) { + return Iterators.emptyIterator(); + } + final Iterator completeRangeItr = this.lowerBoundWindow.lowerBound.isLessThan(this.restriction.lowerBound) ? this.rangesByUpperBound.tailMap(this.restriction.lowerBound, false).values().iterator() : this.rangesByLowerBound.tailMap((Cut)this.lowerBoundWindow.lowerBound.endpoint(), this.lowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values().iterator(); + final Cut upperBoundOnLowerBounds = Ordering.natural().min(this.lowerBoundWindow.upperBound, Cut.belowValue(this.restriction.upperBound)); + return new AbstractIterator, Range>>(){ + + @Override + protected Map.Entry, Range> computeNext() { + if (!completeRangeItr.hasNext()) { + return (Map.Entry)this.endOfData(); + } + Range nextRange = (Range)completeRangeItr.next(); + if (upperBoundOnLowerBounds.isLessThan(nextRange.lowerBound)) { + return (Map.Entry)this.endOfData(); + } + nextRange = nextRange.intersection(SubRangeSetRangesByLowerBound.this.restriction); + return Maps.immutableEntry(nextRange.lowerBound, nextRange); + } + }; + } + + @Override + Iterator, Range>> descendingEntryIterator() { + if (this.restriction.isEmpty()) { + return Iterators.emptyIterator(); + } + Cut upperBoundOnLowerBounds = Ordering.natural().min(this.lowerBoundWindow.upperBound, Cut.belowValue(this.restriction.upperBound)); + final Iterator completeRangeItr = this.rangesByLowerBound.headMap(upperBoundOnLowerBounds.endpoint(), upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED).descendingMap().values().iterator(); + return new AbstractIterator, Range>>(){ + + @Override + protected Map.Entry, Range> computeNext() { + if (!completeRangeItr.hasNext()) { + return (Map.Entry)this.endOfData(); + } + Range nextRange = (Range)completeRangeItr.next(); + if (((SubRangeSetRangesByLowerBound)SubRangeSetRangesByLowerBound.this).restriction.lowerBound.compareTo(nextRange.upperBound) >= 0) { + return (Map.Entry)this.endOfData(); + } + nextRange = nextRange.intersection(SubRangeSetRangesByLowerBound.this.restriction); + if (SubRangeSetRangesByLowerBound.this.lowerBoundWindow.contains(nextRange.lowerBound)) { + return Maps.immutableEntry(nextRange.lowerBound, nextRange); + } + return (Map.Entry)this.endOfData(); + } + }; + } + + @Override + public int size() { + return Iterators.size(this.entryIterator()); + } + } + + private final class Complement + extends TreeRangeSet { + Complement() { + super(new ComplementRangesByLowerBound(TreeRangeSet.this.rangesByLowerBound)); + } + + @Override + public void add(Range rangeToAdd) { + TreeRangeSet.this.remove(rangeToAdd); + } + + @Override + public void remove(Range rangeToRemove) { + TreeRangeSet.this.add(rangeToRemove); + } + + @Override + public boolean contains(C value) { + return !TreeRangeSet.this.contains((Comparable)value); + } + + @Override + public RangeSet complement() { + return TreeRangeSet.this; + } + } + + private static final class ComplementRangesByLowerBound> + extends AbstractNavigableMap, Range> { + private final NavigableMap, Range> positiveRangesByLowerBound; + private final NavigableMap, Range> positiveRangesByUpperBound; + private final Range> complementLowerBoundWindow; + + ComplementRangesByLowerBound(NavigableMap, Range> positiveRangesByLowerBound) { + this(positiveRangesByLowerBound, Range.all()); + } + + private ComplementRangesByLowerBound(NavigableMap, Range> positiveRangesByLowerBound, Range> window) { + this.positiveRangesByLowerBound = positiveRangesByLowerBound; + this.positiveRangesByUpperBound = new RangesByUpperBound(positiveRangesByLowerBound); + this.complementLowerBoundWindow = window; + } + + private NavigableMap, Range> subMap(Range> subWindow) { + if (!this.complementLowerBoundWindow.isConnected(subWindow)) { + return ImmutableSortedMap.of(); + } + subWindow = subWindow.intersection(this.complementLowerBoundWindow); + return new ComplementRangesByLowerBound(this.positiveRangesByLowerBound, subWindow); + } + + @Override + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) { + return this.subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + @Override + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) { + return this.subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + @Override + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) { + return this.subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + @Override + public Comparator> comparator() { + return Ordering.natural(); + } + + @Override + Iterator, Range>> entryIterator() { + Cut firstComplementRangeLowerBound; + Collection positiveRanges = this.complementLowerBoundWindow.hasLowerBound() ? this.positiveRangesByUpperBound.tailMap(this.complementLowerBoundWindow.lowerEndpoint(), this.complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values() : this.positiveRangesByUpperBound.values(); + final PeekingIterator positiveItr = Iterators.peekingIterator(positiveRanges.iterator()); + if (this.complementLowerBoundWindow.contains(Cut.belowAll()) && (!positiveItr.hasNext() || ((Range)positiveItr.peek()).lowerBound != Cut.belowAll())) { + firstComplementRangeLowerBound = Cut.belowAll(); + } else if (positiveItr.hasNext()) { + firstComplementRangeLowerBound = ((Range)positiveItr.next()).upperBound; + } else { + return Iterators.emptyIterator(); + } + return new AbstractIterator, Range>>(){ + Cut nextComplementRangeLowerBound; + { + this.nextComplementRangeLowerBound = firstComplementRangeLowerBound; + } + + @Override + protected Map.Entry, Range> computeNext() { + Range negativeRange; + if (((ComplementRangesByLowerBound)ComplementRangesByLowerBound.this).complementLowerBoundWindow.upperBound.isLessThan(this.nextComplementRangeLowerBound) || this.nextComplementRangeLowerBound == Cut.aboveAll()) { + return (Map.Entry)this.endOfData(); + } + if (positiveItr.hasNext()) { + Range positiveRange = (Range)positiveItr.next(); + negativeRange = Range.create(this.nextComplementRangeLowerBound, positiveRange.lowerBound); + this.nextComplementRangeLowerBound = positiveRange.upperBound; + } else { + negativeRange = Range.create(this.nextComplementRangeLowerBound, Cut.aboveAll()); + this.nextComplementRangeLowerBound = Cut.aboveAll(); + } + return Maps.immutableEntry(negativeRange.lowerBound, negativeRange); + } + }; + } + + @Override + Iterator, Range>> descendingEntryIterator() { + Cut cut; + boolean inclusive; + Cut startingPoint = this.complementLowerBoundWindow.hasUpperBound() ? this.complementLowerBoundWindow.upperEndpoint() : Cut.aboveAll(); + final PeekingIterator positiveItr = Iterators.peekingIterator(this.positiveRangesByUpperBound.headMap(startingPoint, inclusive = this.complementLowerBoundWindow.hasUpperBound() && this.complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED).descendingMap().values().iterator()); + if (positiveItr.hasNext()) { + cut = ((Range)positiveItr.peek()).upperBound == Cut.aboveAll() ? ((Range)positiveItr.next()).lowerBound : this.positiveRangesByLowerBound.higherKey(((Range)positiveItr.peek()).upperBound); + } else { + if (!this.complementLowerBoundWindow.contains(Cut.belowAll()) || this.positiveRangesByLowerBound.containsKey(Cut.belowAll())) { + return Iterators.emptyIterator(); + } + cut = this.positiveRangesByLowerBound.higherKey(Cut.belowAll()); + } + final Cut firstComplementRangeUpperBound = MoreObjects.firstNonNull(cut, Cut.aboveAll()); + return new AbstractIterator, Range>>(){ + Cut nextComplementRangeUpperBound; + { + this.nextComplementRangeUpperBound = firstComplementRangeUpperBound; + } + + @Override + protected Map.Entry, Range> computeNext() { + if (this.nextComplementRangeUpperBound == Cut.belowAll()) { + return (Map.Entry)this.endOfData(); + } + if (positiveItr.hasNext()) { + Range positiveRange = (Range)positiveItr.next(); + Range negativeRange = Range.create(positiveRange.upperBound, this.nextComplementRangeUpperBound); + this.nextComplementRangeUpperBound = positiveRange.lowerBound; + if (((ComplementRangesByLowerBound)ComplementRangesByLowerBound.this).complementLowerBoundWindow.lowerBound.isLessThan(negativeRange.lowerBound)) { + return Maps.immutableEntry(negativeRange.lowerBound, negativeRange); + } + } else if (((ComplementRangesByLowerBound)ComplementRangesByLowerBound.this).complementLowerBoundWindow.lowerBound.isLessThan(Cut.belowAll())) { + Range negativeRange = Range.create(Cut.belowAll(), this.nextComplementRangeUpperBound); + this.nextComplementRangeUpperBound = Cut.belowAll(); + return Maps.immutableEntry(Cut.belowAll(), negativeRange); + } + return (Map.Entry)this.endOfData(); + } + }; + } + + @Override + public int size() { + return Iterators.size(this.entryIterator()); + } + + @Override + @Nullable + public Range get(Object key) { + if (key instanceof Cut) { + try { + Cut cut = (Cut)key; + Map.Entry, Range> firstEntry = this.tailMap(cut, true).firstEntry(); + if (firstEntry != null && firstEntry.getKey().equals(cut)) { + return firstEntry.getValue(); + } + } + catch (ClassCastException e) { + return null; + } + } + return null; + } + + @Override + public boolean containsKey(Object key) { + return this.get(key) != null; + } + } + + @VisibleForTesting + static final class RangesByUpperBound> + extends AbstractNavigableMap, Range> { + private final NavigableMap, Range> rangesByLowerBound; + private final Range> upperBoundWindow; + + RangesByUpperBound(NavigableMap, Range> rangesByLowerBound) { + this.rangesByLowerBound = rangesByLowerBound; + this.upperBoundWindow = Range.all(); + } + + private RangesByUpperBound(NavigableMap, Range> rangesByLowerBound, Range> upperBoundWindow) { + this.rangesByLowerBound = rangesByLowerBound; + this.upperBoundWindow = upperBoundWindow; + } + + private NavigableMap, Range> subMap(Range> window) { + if (window.isConnected(this.upperBoundWindow)) { + return new RangesByUpperBound(this.rangesByLowerBound, window.intersection(this.upperBoundWindow)); + } + return ImmutableSortedMap.of(); + } + + @Override + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) { + return this.subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + @Override + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) { + return this.subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + @Override + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) { + return this.subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + @Override + public Comparator> comparator() { + return Ordering.natural(); + } + + @Override + public boolean containsKey(@Nullable Object key) { + return this.get(key) != null; + } + + @Override + public Range get(@Nullable Object key) { + if (key instanceof Cut) { + try { + Cut cut = (Cut)key; + if (!this.upperBoundWindow.contains(cut)) { + return null; + } + Map.Entry> candidate = this.rangesByLowerBound.lowerEntry(cut); + if (candidate != null && candidate.getValue().upperBound.equals(cut)) { + return candidate.getValue(); + } + } + catch (ClassCastException e) { + return null; + } + } + return null; + } + + @Override + Iterator, Range>> entryIterator() { + Map.Entry, Range> lowerEntry; + final Iterator backingItr = !this.upperBoundWindow.hasLowerBound() ? this.rangesByLowerBound.values().iterator() : ((lowerEntry = this.rangesByLowerBound.lowerEntry(this.upperBoundWindow.lowerEndpoint())) == null ? this.rangesByLowerBound.values().iterator() : (this.upperBoundWindow.lowerBound.isLessThan(lowerEntry.getValue().upperBound) ? this.rangesByLowerBound.tailMap(lowerEntry.getKey(), true).values().iterator() : this.rangesByLowerBound.tailMap(this.upperBoundWindow.lowerEndpoint(), true).values().iterator())); + return new AbstractIterator, Range>>(){ + + @Override + protected Map.Entry, Range> computeNext() { + if (!backingItr.hasNext()) { + return (Map.Entry)this.endOfData(); + } + Range range = (Range)backingItr.next(); + if (((RangesByUpperBound)RangesByUpperBound.this).upperBoundWindow.upperBound.isLessThan(range.upperBound)) { + return (Map.Entry)this.endOfData(); + } + return Maps.immutableEntry(range.upperBound, range); + } + }; + } + + @Override + Iterator, Range>> descendingEntryIterator() { + Collection candidates = this.upperBoundWindow.hasUpperBound() ? this.rangesByLowerBound.headMap(this.upperBoundWindow.upperEndpoint(), false).descendingMap().values() : this.rangesByLowerBound.descendingMap().values(); + final PeekingIterator backingItr = Iterators.peekingIterator(candidates.iterator()); + if (backingItr.hasNext() && this.upperBoundWindow.upperBound.isLessThan(((Range)backingItr.peek()).upperBound)) { + backingItr.next(); + } + return new AbstractIterator, Range>>(){ + + @Override + protected Map.Entry, Range> computeNext() { + if (!backingItr.hasNext()) { + return (Map.Entry)this.endOfData(); + } + Range range = (Range)backingItr.next(); + return ((RangesByUpperBound)RangesByUpperBound.this).upperBoundWindow.lowerBound.isLessThan(range.upperBound) ? Maps.immutableEntry(range.upperBound, range) : (Map.Entry)this.endOfData(); + } + }; + } + + @Override + public int size() { + if (this.upperBoundWindow.equals(Range.all())) { + return this.rangesByLowerBound.size(); + } + return Iterators.size(this.entryIterator()); + } + + @Override + public boolean isEmpty() { + return this.upperBoundWindow.equals(Range.all()) ? this.rangesByLowerBound.isEmpty() : !this.entryIterator().hasNext(); + } + } + + final class AsRanges + extends ForwardingCollection> + implements Set> { + AsRanges() { + } + + @Override + protected Collection> delegate() { + return TreeRangeSet.this.rangesByLowerBound.values(); + } + + @Override + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + @Override + public boolean equals(@Nullable Object o) { + return Sets.equalsImpl(this, o); + } + } +} diff --git a/src/com/google/common/collect/TreeTraverser.java b/src/com/google/common/collect/TreeTraverser.java new file mode 100644 index 0000000..9802c55 --- /dev/null +++ b/src/com/google/common/collect/TreeTraverser.java @@ -0,0 +1,158 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.PeekingIterator; +import com.google.common.collect.UnmodifiableIterator; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Queue; + +@Beta +@GwtCompatible(emulated=true) +public abstract class TreeTraverser { + public abstract Iterable children(T var1); + + public final FluentIterable preOrderTraversal(final T root) { + Preconditions.checkNotNull(root); + return new FluentIterable(){ + + @Override + public UnmodifiableIterator iterator() { + return TreeTraverser.this.preOrderIterator(root); + } + }; + } + + UnmodifiableIterator preOrderIterator(T root) { + return new PreOrderIterator(root); + } + + public final FluentIterable postOrderTraversal(final T root) { + Preconditions.checkNotNull(root); + return new FluentIterable(){ + + @Override + public UnmodifiableIterator iterator() { + return TreeTraverser.this.postOrderIterator(root); + } + }; + } + + UnmodifiableIterator postOrderIterator(T root) { + return new PostOrderIterator(root); + } + + public final FluentIterable breadthFirstTraversal(final T root) { + Preconditions.checkNotNull(root); + return new FluentIterable(){ + + @Override + public UnmodifiableIterator iterator() { + return new BreadthFirstIterator(root); + } + }; + } + + private final class BreadthFirstIterator + extends UnmodifiableIterator + implements PeekingIterator { + private final Queue queue = new ArrayDeque(); + + BreadthFirstIterator(T root) { + this.queue.add(root); + } + + @Override + public boolean hasNext() { + return !this.queue.isEmpty(); + } + + @Override + public T peek() { + return this.queue.element(); + } + + @Override + public T next() { + Object result = this.queue.remove(); + Iterables.addAll(this.queue, TreeTraverser.this.children(result)); + return result; + } + } + + private final class PostOrderIterator + extends AbstractIterator { + private final ArrayDeque> stack = new ArrayDeque(); + + PostOrderIterator(T root) { + this.stack.addLast(this.expand(root)); + } + + @Override + protected T computeNext() { + while (!this.stack.isEmpty()) { + PostOrderNode top = this.stack.getLast(); + if (top.childIterator.hasNext()) { + Object child = top.childIterator.next(); + this.stack.addLast(this.expand(child)); + continue; + } + this.stack.removeLast(); + return top.root; + } + return this.endOfData(); + } + + private PostOrderNode expand(T t) { + return new PostOrderNode(t, TreeTraverser.this.children(t).iterator()); + } + } + + private static final class PostOrderNode { + final T root; + final Iterator childIterator; + + PostOrderNode(T root, Iterator childIterator) { + this.root = Preconditions.checkNotNull(root); + this.childIterator = Preconditions.checkNotNull(childIterator); + } + } + + private final class PreOrderIterator + extends UnmodifiableIterator { + private final Deque> stack = new ArrayDeque(); + + PreOrderIterator(T root) { + this.stack.addLast(Iterators.singletonIterator(Preconditions.checkNotNull(root))); + } + + @Override + public boolean hasNext() { + return !this.stack.isEmpty(); + } + + @Override + public T next() { + Iterator childItr; + Iterator itr = this.stack.getLast(); + Object result = Preconditions.checkNotNull(itr.next()); + if (!itr.hasNext()) { + this.stack.removeLast(); + } + if ((childItr = TreeTraverser.this.children(result).iterator()).hasNext()) { + this.stack.addLast(childItr); + } + return result; + } + } +} diff --git a/src/com/google/common/collect/UnmodifiableIterator.java b/src/com/google/common/collect/UnmodifiableIterator.java new file mode 100644 index 0000000..44a767a --- /dev/null +++ b/src/com/google/common/collect/UnmodifiableIterator.java @@ -0,0 +1,20 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; + +@GwtCompatible +public abstract class UnmodifiableIterator +implements Iterator { + protected UnmodifiableIterator() { + } + + @Override + @Deprecated + public final void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/UnmodifiableListIterator.java b/src/com/google/common/collect/UnmodifiableListIterator.java new file mode 100644 index 0000000..6c0297a --- /dev/null +++ b/src/com/google/common/collect/UnmodifiableListIterator.java @@ -0,0 +1,28 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.UnmodifiableIterator; +import java.util.ListIterator; + +@GwtCompatible +public abstract class UnmodifiableListIterator +extends UnmodifiableIterator +implements ListIterator { + protected UnmodifiableListIterator() { + } + + @Override + @Deprecated + public final void add(E e) { + throw new UnsupportedOperationException(); + } + + @Override + @Deprecated + public final void set(E e) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/common/collect/UnmodifiableSortedMultiset.java b/src/com/google/common/collect/UnmodifiableSortedMultiset.java new file mode 100644 index 0000000..6899280 --- /dev/null +++ b/src/com/google/common/collect/UnmodifiableSortedMultiset.java @@ -0,0 +1,92 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.BoundType; +import com.google.common.collect.Multiset; +import com.google.common.collect.Multisets; +import com.google.common.collect.Sets; +import com.google.common.collect.SortedMultiset; +import java.util.Comparator; +import java.util.NavigableSet; + +@GwtCompatible(emulated=true) +final class UnmodifiableSortedMultiset +extends Multisets.UnmodifiableMultiset +implements SortedMultiset { + private transient UnmodifiableSortedMultiset descendingMultiset; + private static final long serialVersionUID = 0L; + + UnmodifiableSortedMultiset(SortedMultiset delegate) { + super(delegate); + } + + @Override + protected SortedMultiset delegate() { + return (SortedMultiset)super.delegate(); + } + + @Override + public Comparator comparator() { + return this.delegate().comparator(); + } + + @Override + NavigableSet createElementSet() { + return Sets.unmodifiableNavigableSet(this.delegate().elementSet()); + } + + @Override + public NavigableSet elementSet() { + return (NavigableSet)super.elementSet(); + } + + @Override + public SortedMultiset descendingMultiset() { + UnmodifiableSortedMultiset result = this.descendingMultiset; + if (result == null) { + result = new UnmodifiableSortedMultiset(this.delegate().descendingMultiset()); + result.descendingMultiset = this; + this.descendingMultiset = result; + return this.descendingMultiset; + } + return result; + } + + @Override + public Multiset.Entry firstEntry() { + return this.delegate().firstEntry(); + } + + @Override + public Multiset.Entry lastEntry() { + return this.delegate().lastEntry(); + } + + @Override + public Multiset.Entry pollFirstEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public Multiset.Entry pollLastEntry() { + throw new UnsupportedOperationException(); + } + + @Override + public SortedMultiset headMultiset(E upperBound, BoundType boundType) { + return Multisets.unmodifiableSortedMultiset(this.delegate().headMultiset(upperBound, boundType)); + } + + @Override + public SortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) { + return Multisets.unmodifiableSortedMultiset(this.delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType)); + } + + @Override + public SortedMultiset tailMultiset(E lowerBound, BoundType boundType) { + return Multisets.unmodifiableSortedMultiset(this.delegate().tailMultiset(lowerBound, boundType)); + } +} diff --git a/src/com/google/common/collect/UsingToStringOrdering.java b/src/com/google/common/collect/UsingToStringOrdering.java new file mode 100644 index 0000000..23de6dc --- /dev/null +++ b/src/com/google/common/collect/UsingToStringOrdering.java @@ -0,0 +1,32 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Ordering; +import java.io.Serializable; + +@GwtCompatible(serializable=true) +final class UsingToStringOrdering +extends Ordering +implements Serializable { + static final UsingToStringOrdering INSTANCE = new UsingToStringOrdering(); + private static final long serialVersionUID = 0L; + + @Override + public int compare(Object left, Object right) { + return left.toString().compareTo(right.toString()); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() { + return "Ordering.usingToString()"; + } + + private UsingToStringOrdering() { + } +} diff --git a/src/com/google/common/collect/WellBehavedMap.java b/src/com/google/common/collect/WellBehavedMap.java new file mode 100644 index 0000000..4021c30 --- /dev/null +++ b/src/com/google/common/collect/WellBehavedMap.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.AbstractMapEntry; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.Maps; +import com.google.common.collect.TransformedIterator; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +@GwtCompatible +final class WellBehavedMap +extends ForwardingMap { + private final Map delegate; + private Set> entrySet; + + private WellBehavedMap(Map delegate) { + this.delegate = delegate; + } + + static WellBehavedMap wrap(Map delegate) { + return new WellBehavedMap(delegate); + } + + @Override + protected Map delegate() { + return this.delegate; + } + + @Override + public Set> entrySet() { + Set> es = this.entrySet; + if (es != null) { + return es; + } + this.entrySet = new EntrySet(); + return this.entrySet; + } + + private final class EntrySet + extends Maps.EntrySet { + private EntrySet() { + } + + @Override + Map map() { + return WellBehavedMap.this; + } + + @Override + public Iterator> iterator() { + return new TransformedIterator>(WellBehavedMap.this.keySet().iterator()){ + + @Override + Map.Entry transform(final K key) { + return new AbstractMapEntry(){ + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return WellBehavedMap.this.get(key); + } + + @Override + public V setValue(V value) { + return WellBehavedMap.this.put(key, value); + } + }; + } + }; + } + } +} diff --git a/src/com/google/common/collect/package-info.java b/src/com/google/common/collect/package-info.java new file mode 100644 index 0000000..a9887e5 --- /dev/null +++ b/src/com/google/common/collect/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.collect; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/escape/ArrayBasedCharEscaper.java b/src/com/google/common/escape/ArrayBasedCharEscaper.java new file mode 100644 index 0000000..2764a56 --- /dev/null +++ b/src/com/google/common/escape/ArrayBasedCharEscaper.java @@ -0,0 +1,62 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.ArrayBasedEscaperMap; +import com.google.common.escape.CharEscaper; +import java.util.Map; + +@Beta +@GwtCompatible +public abstract class ArrayBasedCharEscaper +extends CharEscaper { + private final char[][] replacements; + private final int replacementsLength; + private final char safeMin; + private final char safeMax; + + protected ArrayBasedCharEscaper(Map replacementMap, char safeMin, char safeMax) { + this(ArrayBasedEscaperMap.create(replacementMap), safeMin, safeMax); + } + + protected ArrayBasedCharEscaper(ArrayBasedEscaperMap escaperMap, char safeMin, char safeMax) { + Preconditions.checkNotNull(escaperMap); + this.replacements = escaperMap.getReplacementArray(); + this.replacementsLength = this.replacements.length; + if (safeMax < safeMin) { + safeMax = '\u0000'; + safeMin = (char)65535; + } + this.safeMin = safeMin; + this.safeMax = safeMax; + } + + @Override + public final String escape(String s) { + Preconditions.checkNotNull(s); + for (int i = 0; i < s.length(); ++i) { + char c = s.charAt(i); + if ((c >= this.replacementsLength || this.replacements[c] == null) && c <= this.safeMax && c >= this.safeMin) continue; + return this.escapeSlow(s, i); + } + return s; + } + + @Override + protected final char[] escape(char c) { + char[] chars; + if (c < this.replacementsLength && (chars = this.replacements[c]) != null) { + return chars; + } + if (c >= this.safeMin && c <= this.safeMax) { + return null; + } + return this.escapeUnsafe(c); + } + + protected abstract char[] escapeUnsafe(char var1); +} diff --git a/src/com/google/common/escape/ArrayBasedEscaperMap.java b/src/com/google/common/escape/ArrayBasedEscaperMap.java new file mode 100644 index 0000000..5d3766b --- /dev/null +++ b/src/com/google/common/escape/ArrayBasedEscaperMap.java @@ -0,0 +1,44 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.Map; + +@Beta +@GwtCompatible +public final class ArrayBasedEscaperMap { + private final char[][] replacementArray; + private static final char[][] EMPTY_REPLACEMENT_ARRAY = new char[0][0]; + + public static ArrayBasedEscaperMap create(Map replacements) { + return new ArrayBasedEscaperMap(ArrayBasedEscaperMap.createReplacementArray(replacements)); + } + + private ArrayBasedEscaperMap(char[][] replacementArray) { + this.replacementArray = replacementArray; + } + + char[][] getReplacementArray() { + return this.replacementArray; + } + + @VisibleForTesting + static char[][] createReplacementArray(Map map) { + Preconditions.checkNotNull(map); + if (map.isEmpty()) { + return EMPTY_REPLACEMENT_ARRAY; + } + char max = Collections.max(map.keySet()).charValue(); + char[][] replacements = new char[max + '\u0001'][]; + for (char c : map.keySet()) { + replacements[c] = map.get(Character.valueOf(c)).toCharArray(); + } + return replacements; + } +} diff --git a/src/com/google/common/escape/ArrayBasedUnicodeEscaper.java b/src/com/google/common/escape/ArrayBasedUnicodeEscaper.java new file mode 100644 index 0000000..02a2dc4 --- /dev/null +++ b/src/com/google/common/escape/ArrayBasedUnicodeEscaper.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.ArrayBasedEscaperMap; +import com.google.common.escape.UnicodeEscaper; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public abstract class ArrayBasedUnicodeEscaper +extends UnicodeEscaper { + private final char[][] replacements; + private final int replacementsLength; + private final int safeMin; + private final int safeMax; + private final char safeMinChar; + private final char safeMaxChar; + + protected ArrayBasedUnicodeEscaper(Map replacementMap, int safeMin, int safeMax, @Nullable String unsafeReplacement) { + this(ArrayBasedEscaperMap.create(replacementMap), safeMin, safeMax, unsafeReplacement); + } + + protected ArrayBasedUnicodeEscaper(ArrayBasedEscaperMap escaperMap, int safeMin, int safeMax, @Nullable String unsafeReplacement) { + Preconditions.checkNotNull(escaperMap); + this.replacements = escaperMap.getReplacementArray(); + this.replacementsLength = this.replacements.length; + if (safeMax < safeMin) { + safeMax = -1; + safeMin = Integer.MAX_VALUE; + } + this.safeMin = safeMin; + this.safeMax = safeMax; + if (safeMin >= 55296) { + this.safeMinChar = (char)65535; + this.safeMaxChar = '\u0000'; + } else { + this.safeMinChar = (char)safeMin; + this.safeMaxChar = (char)Math.min(safeMax, 55295); + } + } + + @Override + public final String escape(String s) { + Preconditions.checkNotNull(s); + for (int i = 0; i < s.length(); ++i) { + char c = s.charAt(i); + if ((c >= this.replacementsLength || this.replacements[c] == null) && c <= this.safeMaxChar && c >= this.safeMinChar) continue; + return this.escapeSlow(s, i); + } + return s; + } + + @Override + protected final int nextEscapeIndex(CharSequence csq, int index, int end) { + char c; + while (index < end && ((c = csq.charAt(index)) >= this.replacementsLength || this.replacements[c] == null) && c <= this.safeMaxChar && c >= this.safeMinChar) { + ++index; + } + return index; + } + + @Override + protected final char[] escape(int cp) { + char[] chars; + if (cp < this.replacementsLength && (chars = this.replacements[cp]) != null) { + return chars; + } + if (cp >= this.safeMin && cp <= this.safeMax) { + return null; + } + return this.escapeUnsafe(cp); + } + + protected abstract char[] escapeUnsafe(int var1); +} diff --git a/src/com/google/common/escape/CharEscaper.java b/src/com/google/common/escape/CharEscaper.java new file mode 100644 index 0000000..c5d7aa0 --- /dev/null +++ b/src/com/google/common/escape/CharEscaper.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.Escaper; +import com.google.common.escape.Platform; + +@Beta +@GwtCompatible +public abstract class CharEscaper +extends Escaper { + private static final int DEST_PAD_MULTIPLIER = 2; + + protected CharEscaper() { + } + + @Override + public String escape(String string) { + Preconditions.checkNotNull(string); + int length = string.length(); + for (int index = 0; index < length; ++index) { + if (this.escape(string.charAt(index)) == null) continue; + return this.escapeSlow(string, index); + } + return string; + } + + protected final String escapeSlow(String s, int index) { + int slen = s.length(); + char[] dest = Platform.charBufferFromThreadLocal(); + int destSize = dest.length; + int destIndex = 0; + int lastEscape = 0; + while (index < slen) { + char[] r = this.escape(s.charAt(index)); + if (r != null) { + int charsSkipped = index - lastEscape; + int rlen = r.length; + int sizeNeeded = destIndex + charsSkipped + rlen; + if (destSize < sizeNeeded) { + destSize = sizeNeeded + 2 * (slen - index); + dest = CharEscaper.growBuffer(dest, destIndex, destSize); + } + if (charsSkipped > 0) { + s.getChars(lastEscape, index, dest, destIndex); + destIndex += charsSkipped; + } + if (rlen > 0) { + System.arraycopy(r, 0, dest, destIndex, rlen); + destIndex += rlen; + } + lastEscape = index + 1; + } + ++index; + } + int charsLeft = slen - lastEscape; + if (charsLeft > 0) { + int sizeNeeded = destIndex + charsLeft; + if (destSize < sizeNeeded) { + dest = CharEscaper.growBuffer(dest, destIndex, sizeNeeded); + } + s.getChars(lastEscape, slen, dest, destIndex); + destIndex = sizeNeeded; + } + return new String(dest, 0, destIndex); + } + + protected abstract char[] escape(char var1); + + private static char[] growBuffer(char[] dest, int index, int size) { + char[] copy = new char[size]; + if (index > 0) { + System.arraycopy(dest, 0, copy, 0, index); + } + return copy; + } +} diff --git a/src/com/google/common/escape/CharEscaperBuilder.java b/src/com/google/common/escape/CharEscaperBuilder.java new file mode 100644 index 0000000..ff56f14 --- /dev/null +++ b/src/com/google/common/escape/CharEscaperBuilder.java @@ -0,0 +1,74 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.CharEscaper; +import com.google.common.escape.Escaper; +import java.util.HashMap; +import java.util.Map; + +@Beta +@GwtCompatible +public final class CharEscaperBuilder { + private final Map map = new HashMap(); + private int max = -1; + + public CharEscaperBuilder addEscape(char c, String r) { + this.map.put(Character.valueOf(c), Preconditions.checkNotNull(r)); + if (c > this.max) { + this.max = c; + } + return this; + } + + public CharEscaperBuilder addEscapes(char[] cs, String r) { + Preconditions.checkNotNull(r); + for (char c : cs) { + this.addEscape(c, r); + } + return this; + } + + public char[][] toArray() { + char[][] result = new char[this.max + 1][]; + for (Map.Entry entry : this.map.entrySet()) { + result[entry.getKey().charValue()] = entry.getValue().toCharArray(); + } + return result; + } + + public Escaper toEscaper() { + return new CharArrayDecorator(this.toArray()); + } + + private static class CharArrayDecorator + extends CharEscaper { + private final char[][] replacements; + private final int replaceLength; + + CharArrayDecorator(char[][] replacements) { + this.replacements = replacements; + this.replaceLength = replacements.length; + } + + @Override + public String escape(String s) { + int slen = s.length(); + for (int index = 0; index < slen; ++index) { + char c = s.charAt(index); + if (c >= this.replacements.length || this.replacements[c] == null) continue; + return this.escapeSlow(s, index); + } + return s; + } + + @Override + protected char[] escape(char c) { + return c < this.replaceLength ? this.replacements[c] : null; + } + } +} diff --git a/src/com/google/common/escape/Escaper.java b/src/com/google/common/escape/Escaper.java new file mode 100644 index 0000000..73c91ce --- /dev/null +++ b/src/com/google/common/escape/Escaper.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; + +@Beta +@GwtCompatible +public abstract class Escaper { + private final Function asFunction = new Function(){ + + @Override + public String apply(String from) { + return Escaper.this.escape(from); + } + }; + + protected Escaper() { + } + + public abstract String escape(String var1); + + public final Function asFunction() { + return this.asFunction; + } +} diff --git a/src/com/google/common/escape/Escapers.java b/src/com/google/common/escape/Escapers.java new file mode 100644 index 0000000..fbf1b98 --- /dev/null +++ b/src/com/google/common/escape/Escapers.java @@ -0,0 +1,147 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.ArrayBasedCharEscaper; +import com.google.common.escape.CharEscaper; +import com.google.common.escape.Escaper; +import com.google.common.escape.UnicodeEscaper; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class Escapers { + private static final Escaper NULL_ESCAPER = new CharEscaper(){ + + @Override + public String escape(String string) { + return Preconditions.checkNotNull(string); + } + + @Override + protected char[] escape(char c) { + return null; + } + }; + + private Escapers() { + } + + public static Escaper nullEscaper() { + return NULL_ESCAPER; + } + + public static Builder builder() { + return new Builder(); + } + + static UnicodeEscaper asUnicodeEscaper(Escaper escaper) { + Preconditions.checkNotNull(escaper); + if (escaper instanceof UnicodeEscaper) { + return (UnicodeEscaper)escaper; + } + if (escaper instanceof CharEscaper) { + return Escapers.wrap((CharEscaper)escaper); + } + String string = String.valueOf(escaper.getClass().getName()); + throw new IllegalArgumentException(string.length() != 0 ? "Cannot create a UnicodeEscaper from: ".concat(string) : new String("Cannot create a UnicodeEscaper from: ")); + } + + public static String computeReplacement(CharEscaper escaper, char c) { + return Escapers.stringOrNull(escaper.escape(c)); + } + + public static String computeReplacement(UnicodeEscaper escaper, int cp) { + return Escapers.stringOrNull(escaper.escape(cp)); + } + + private static String stringOrNull(char[] in) { + return in == null ? null : new String(in); + } + + private static UnicodeEscaper wrap(final CharEscaper escaper) { + return new UnicodeEscaper(){ + + @Override + protected char[] escape(int cp) { + int n; + if (cp < 65536) { + return escaper.escape((char)cp); + } + char[] surrogateChars = new char[2]; + Character.toChars(cp, surrogateChars, 0); + char[] hiChars = escaper.escape(surrogateChars[0]); + char[] loChars = escaper.escape(surrogateChars[1]); + if (hiChars == null && loChars == null) { + return null; + } + int hiCount = hiChars != null ? hiChars.length : 1; + int loCount = loChars != null ? loChars.length : 1; + char[] output = new char[hiCount + loCount]; + if (hiChars != null) { + for (n = 0; n < hiChars.length; ++n) { + output[n] = hiChars[n]; + } + } else { + output[0] = surrogateChars[0]; + } + if (loChars != null) { + for (n = 0; n < loChars.length; ++n) { + output[hiCount + n] = loChars[n]; + } + } else { + output[hiCount] = surrogateChars[1]; + } + return output; + } + }; + } + + @Beta + public static final class Builder { + private final Map replacementMap = new HashMap(); + private char safeMin = '\u0000'; + private char safeMax = (char)65535; + private String unsafeReplacement = null; + + private Builder() { + } + + public Builder setSafeRange(char safeMin, char safeMax) { + this.safeMin = safeMin; + this.safeMax = safeMax; + return this; + } + + public Builder setUnsafeReplacement(@Nullable String unsafeReplacement) { + this.unsafeReplacement = unsafeReplacement; + return this; + } + + public Builder addEscape(char c, String replacement) { + Preconditions.checkNotNull(replacement); + this.replacementMap.put(Character.valueOf(c), replacement); + return this; + } + + public Escaper build() { + return new ArrayBasedCharEscaper(this.replacementMap, this.safeMin, this.safeMax){ + private final char[] replacementChars; + { + this.replacementChars = Builder.this.unsafeReplacement != null ? Builder.this.unsafeReplacement.toCharArray() : null; + } + + @Override + protected char[] escapeUnsafe(char c) { + return this.replacementChars; + } + }; + } + } +} diff --git a/src/com/google/common/escape/Platform.java b/src/com/google/common/escape/Platform.java new file mode 100644 index 0000000..c669e02 --- /dev/null +++ b/src/com/google/common/escape/Platform.java @@ -0,0 +1,24 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +final class Platform { + private static final ThreadLocal DEST_TL = new ThreadLocal(){ + + @Override + protected char[] initialValue() { + return new char[1024]; + } + }; + + private Platform() { + } + + static char[] charBufferFromThreadLocal() { + return DEST_TL.get(); + } +} diff --git a/src/com/google/common/escape/UnicodeEscaper.java b/src/com/google/common/escape/UnicodeEscaper.java new file mode 100644 index 0000000..179c563 --- /dev/null +++ b/src/com/google/common/escape/UnicodeEscaper.java @@ -0,0 +1,119 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.Escaper; +import com.google.common.escape.Platform; + +@Beta +@GwtCompatible +public abstract class UnicodeEscaper +extends Escaper { + private static final int DEST_PAD = 32; + + protected UnicodeEscaper() { + } + + protected abstract char[] escape(int var1); + + protected int nextEscapeIndex(CharSequence csq, int start, int end) { + int index; + int cp; + for (index = start; index < end && (cp = UnicodeEscaper.codePointAt(csq, index, end)) >= 0 && this.escape(cp) == null; index += Character.isSupplementaryCodePoint(cp) ? 2 : 1) { + } + return index; + } + + @Override + public String escape(String string) { + Preconditions.checkNotNull(string); + int end = string.length(); + int index = this.nextEscapeIndex(string, 0, end); + return index == end ? string : this.escapeSlow(string, index); + } + + protected final String escapeSlow(String s, int index) { + int end = s.length(); + char[] dest = Platform.charBufferFromThreadLocal(); + int destIndex = 0; + int unescapedChunkStart = 0; + while (index < end) { + int cp = UnicodeEscaper.codePointAt(s, index, end); + if (cp < 0) { + throw new IllegalArgumentException("Trailing high surrogate at end of input"); + } + char[] escaped = this.escape(cp); + int nextIndex = index + (Character.isSupplementaryCodePoint(cp) ? 2 : 1); + if (escaped != null) { + int charsSkipped = index - unescapedChunkStart; + int sizeNeeded = destIndex + charsSkipped + escaped.length; + if (dest.length < sizeNeeded) { + int destLength = sizeNeeded + (end - index) + 32; + dest = UnicodeEscaper.growBuffer(dest, destIndex, destLength); + } + if (charsSkipped > 0) { + s.getChars(unescapedChunkStart, index, dest, destIndex); + destIndex += charsSkipped; + } + if (escaped.length > 0) { + System.arraycopy(escaped, 0, dest, destIndex, escaped.length); + destIndex += escaped.length; + } + unescapedChunkStart = nextIndex; + } + index = this.nextEscapeIndex(s, nextIndex, end); + } + int charsSkipped = end - unescapedChunkStart; + if (charsSkipped > 0) { + int endIndex = destIndex + charsSkipped; + if (dest.length < endIndex) { + dest = UnicodeEscaper.growBuffer(dest, destIndex, endIndex); + } + s.getChars(unescapedChunkStart, end, dest, destIndex); + destIndex = endIndex; + } + return new String(dest, 0, destIndex); + } + + protected static int codePointAt(CharSequence seq, int index, int end) { + Preconditions.checkNotNull(seq); + if (index < end) { + char c1; + if ((c1 = seq.charAt(index++)) < '\ud800' || c1 > '\udfff') { + return c1; + } + if (c1 <= '\udbff') { + if (index == end) { + return -c1; + } + char c2 = seq.charAt(index); + if (Character.isLowSurrogate(c2)) { + return Character.toCodePoint(c1, c2); + } + char c = c2; + char c3 = c2; + int n = index; + String string = String.valueOf(String.valueOf(seq)); + throw new IllegalArgumentException(new StringBuilder(89 + string.length()).append("Expected low surrogate but got char '").append(c).append("' with value ").append((int)c3).append(" at index ").append(n).append(" in '").append(string).append("'").toString()); + } + char c = c1; + char c4 = c1; + int n = index - 1; + String string = String.valueOf(String.valueOf(seq)); + throw new IllegalArgumentException(new StringBuilder(88 + string.length()).append("Unexpected low surrogate character '").append(c).append("' with value ").append((int)c4).append(" at index ").append(n).append(" in '").append(string).append("'").toString()); + } + throw new IndexOutOfBoundsException("Index exceeds specified range"); + } + + private static char[] growBuffer(char[] dest, int index, int size) { + char[] copy = new char[size]; + if (index > 0) { + System.arraycopy(dest, 0, copy, 0, index); + } + return copy; + } +} diff --git a/src/com/google/common/escape/package-info.java b/src/com/google/common/escape/package-info.java new file mode 100644 index 0000000..8ebd789 --- /dev/null +++ b/src/com/google/common/escape/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.escape; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/eventbus/AllowConcurrentEvents.java b/src/com/google/common/eventbus/AllowConcurrentEvents.java new file mode 100644 index 0000000..1978116 --- /dev/null +++ b/src/com/google/common/eventbus/AllowConcurrentEvents.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.METHOD}) +@Beta +public @interface AllowConcurrentEvents { +} diff --git a/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java b/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java new file mode 100644 index 0000000..7d83739 --- /dev/null +++ b/src/com/google/common/eventbus/AnnotatedSubscriberFinder.java @@ -0,0 +1,114 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.base.Objects; +import com.google.common.base.Throwables; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.eventbus.AllowConcurrentEvents; +import com.google.common.eventbus.EventSubscriber; +import com.google.common.eventbus.Subscribe; +import com.google.common.eventbus.SubscriberFindingStrategy; +import com.google.common.eventbus.SynchronizedEventSubscriber; +import com.google.common.reflect.TypeToken; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Set; +import javax.annotation.Nullable; + +class AnnotatedSubscriberFinder +implements SubscriberFindingStrategy { + private static final LoadingCache, ImmutableList> subscriberMethodsCache = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader, ImmutableList>(){ + + @Override + public ImmutableList load(Class concreteClass) throws Exception { + return AnnotatedSubscriberFinder.getAnnotatedMethodsInternal(concreteClass); + } + }); + + AnnotatedSubscriberFinder() { + } + + @Override + public Multimap, EventSubscriber> findAllSubscribers(Object listener) { + HashMultimap, EventSubscriber> methodsInListener = HashMultimap.create(); + Class clazz = listener.getClass(); + for (Method method : AnnotatedSubscriberFinder.getAnnotatedMethods(clazz)) { + Class[] parameterTypes = method.getParameterTypes(); + Class eventType = parameterTypes[0]; + EventSubscriber subscriber = AnnotatedSubscriberFinder.makeSubscriber(listener, method); + methodsInListener.put(eventType, subscriber); + } + return methodsInListener; + } + + private static ImmutableList getAnnotatedMethods(Class clazz) { + try { + return subscriberMethodsCache.getUnchecked(clazz); + } + catch (UncheckedExecutionException e) { + throw Throwables.propagate(e.getCause()); + } + } + + private static ImmutableList getAnnotatedMethodsInternal(Class clazz) { + Set supers = TypeToken.of(clazz).getTypes().rawTypes(); + HashMap identifiers = Maps.newHashMap(); + for (Class superClazz : supers) { + for (Method superClazzMethod : superClazz.getMethods()) { + if (!superClazzMethod.isAnnotationPresent(Subscribe.class) || superClazzMethod.isBridge()) continue; + Class[] parameterTypes = superClazzMethod.getParameterTypes(); + if (parameterTypes.length != 1) { + String string = String.valueOf(String.valueOf(superClazzMethod)); + int n = parameterTypes.length; + throw new IllegalArgumentException(new StringBuilder(128 + string.length()).append("Method ").append(string).append(" has @Subscribe annotation, but requires ").append(n).append(" arguments. Event subscriber methods must require a single argument.").toString()); + } + MethodIdentifier ident = new MethodIdentifier(superClazzMethod); + if (identifiers.containsKey(ident)) continue; + identifiers.put(ident, superClazzMethod); + } + } + return ImmutableList.copyOf(identifiers.values()); + } + + private static EventSubscriber makeSubscriber(Object listener, Method method) { + EventSubscriber wrapper = AnnotatedSubscriberFinder.methodIsDeclaredThreadSafe(method) ? new EventSubscriber(listener, method) : new SynchronizedEventSubscriber(listener, method); + return wrapper; + } + + private static boolean methodIsDeclaredThreadSafe(Method method) { + return method.getAnnotation(AllowConcurrentEvents.class) != null; + } + + private static final class MethodIdentifier { + private final String name; + private final List> parameterTypes; + + MethodIdentifier(Method method) { + this.name = method.getName(); + this.parameterTypes = Arrays.asList(method.getParameterTypes()); + } + + public int hashCode() { + return Objects.hashCode(this.name, this.parameterTypes); + } + + public boolean equals(@Nullable Object o) { + if (o instanceof MethodIdentifier) { + MethodIdentifier ident = (MethodIdentifier)o; + return this.name.equals(ident.name) && this.parameterTypes.equals(ident.parameterTypes); + } + return false; + } + } +} diff --git a/src/com/google/common/eventbus/AsyncEventBus.java b/src/com/google/common/eventbus/AsyncEventBus.java new file mode 100644 index 0000000..b631093 --- /dev/null +++ b/src/com/google/common/eventbus/AsyncEventBus.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.EventSubscriber; +import com.google.common.eventbus.SubscriberExceptionHandler; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executor; + +@Beta +public class AsyncEventBus +extends EventBus { + private final Executor executor; + private final ConcurrentLinkedQueue eventsToDispatch = new ConcurrentLinkedQueue(); + + public AsyncEventBus(String identifier, Executor executor) { + super(identifier); + this.executor = Preconditions.checkNotNull(executor); + } + + public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) { + super(subscriberExceptionHandler); + this.executor = Preconditions.checkNotNull(executor); + } + + public AsyncEventBus(Executor executor) { + super("default"); + this.executor = Preconditions.checkNotNull(executor); + } + + @Override + void enqueueEvent(Object event, EventSubscriber subscriber) { + this.eventsToDispatch.offer(new EventBus.EventWithSubscriber(event, subscriber)); + } + + @Override + protected void dispatchQueuedEvents() { + EventBus.EventWithSubscriber eventWithSubscriber; + while ((eventWithSubscriber = this.eventsToDispatch.poll()) != null) { + this.dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber); + } + } + + @Override + void dispatch(final Object event, final EventSubscriber subscriber) { + Preconditions.checkNotNull(event); + Preconditions.checkNotNull(subscriber); + this.executor.execute(new Runnable(){ + + @Override + public void run() { + AsyncEventBus.super.dispatch(event, subscriber); + } + }); + } +} diff --git a/src/com/google/common/eventbus/DeadEvent.java b/src/com/google/common/eventbus/DeadEvent.java new file mode 100644 index 0000000..fe1aa11 --- /dev/null +++ b/src/com/google/common/eventbus/DeadEvent.java @@ -0,0 +1,26 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; + +@Beta +public class DeadEvent { + private final Object source; + private final Object event; + + public DeadEvent(Object source, Object event) { + this.source = Preconditions.checkNotNull(source); + this.event = Preconditions.checkNotNull(event); + } + + public Object getSource() { + return this.source; + } + + public Object getEvent() { + return this.event; + } +} diff --git a/src/com/google/common/eventbus/EventBus.java b/src/com/google/common/eventbus/EventBus.java new file mode 100644 index 0000000..442a73f --- /dev/null +++ b/src/com/google/common/eventbus/EventBus.java @@ -0,0 +1,214 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; +import com.google.common.eventbus.AnnotatedSubscriberFinder; +import com.google.common.eventbus.DeadEvent; +import com.google.common.eventbus.EventSubscriber; +import com.google.common.eventbus.SubscriberExceptionContext; +import com.google.common.eventbus.SubscriberExceptionHandler; +import com.google.common.eventbus.SubscriberFindingStrategy; +import com.google.common.reflect.TypeToken; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Beta +public class EventBus { + private static final LoadingCache, Set>> flattenHierarchyCache = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader, Set>>(){ + + @Override + public Set> load(Class concreteClass) { + return TypeToken.of(concreteClass).getTypes().rawTypes(); + } + }); + private final SetMultimap, EventSubscriber> subscribersByType = HashMultimap.create(); + private final ReadWriteLock subscribersByTypeLock = new ReentrantReadWriteLock(); + private final SubscriberFindingStrategy finder = new AnnotatedSubscriberFinder(); + private final ThreadLocal> eventsToDispatch = new ThreadLocal>(){ + + @Override + protected Queue initialValue() { + return new LinkedList(); + } + }; + private final ThreadLocal isDispatching = new ThreadLocal(){ + + @Override + protected Boolean initialValue() { + return false; + } + }; + private SubscriberExceptionHandler subscriberExceptionHandler; + + public EventBus() { + this("default"); + } + + public EventBus(String identifier) { + this(new LoggingSubscriberExceptionHandler(identifier)); + } + + public EventBus(SubscriberExceptionHandler subscriberExceptionHandler) { + this.subscriberExceptionHandler = Preconditions.checkNotNull(subscriberExceptionHandler); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void register(Object object) { + Multimap, EventSubscriber> methodsInListener = this.finder.findAllSubscribers(object); + this.subscribersByTypeLock.writeLock().lock(); + try { + this.subscribersByType.putAll(methodsInListener); + } + finally { + this.subscribersByTypeLock.writeLock().unlock(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void unregister(Object object) { + Multimap, EventSubscriber> methodsInListener = this.finder.findAllSubscribers(object); + for (Map.Entry, Collection> entry : methodsInListener.asMap().entrySet()) { + Class eventType = entry.getKey(); + Collection eventMethodsInListener = entry.getValue(); + this.subscribersByTypeLock.writeLock().lock(); + try { + Set currentSubscribers = this.subscribersByType.get(eventType); + if (!currentSubscribers.containsAll(eventMethodsInListener)) { + String string = String.valueOf(String.valueOf(object)); + throw new IllegalArgumentException(new StringBuilder(65 + string.length()).append("missing event subscriber for an annotated method. Is ").append(string).append(" registered?").toString()); + } + currentSubscribers.removeAll(eventMethodsInListener); + } + finally { + this.subscribersByTypeLock.writeLock().unlock(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void post(Object event) { + Set> dispatchTypes = this.flattenHierarchy(event.getClass()); + boolean dispatched = false; + for (Class eventType : dispatchTypes) { + this.subscribersByTypeLock.readLock().lock(); + try { + Set wrappers = this.subscribersByType.get(eventType); + if (wrappers.isEmpty()) continue; + dispatched = true; + for (EventSubscriber wrapper : wrappers) { + this.enqueueEvent(event, wrapper); + } + } + finally { + this.subscribersByTypeLock.readLock().unlock(); + } + } + if (!dispatched && !(event instanceof DeadEvent)) { + this.post(new DeadEvent(this, event)); + } + this.dispatchQueuedEvents(); + } + + void enqueueEvent(Object event, EventSubscriber subscriber) { + this.eventsToDispatch.get().offer(new EventWithSubscriber(event, subscriber)); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void dispatchQueuedEvents() { + if (this.isDispatching.get().booleanValue()) { + return; + } + this.isDispatching.set(true); + try { + EventWithSubscriber eventWithSubscriber; + Queue events = this.eventsToDispatch.get(); + while ((eventWithSubscriber = events.poll()) != null) { + this.dispatch(eventWithSubscriber.event, eventWithSubscriber.subscriber); + } + } + finally { + this.isDispatching.remove(); + this.eventsToDispatch.remove(); + } + } + + void dispatch(Object event, EventSubscriber wrapper) { + try { + wrapper.handleEvent(event); + } + catch (InvocationTargetException e) { + try { + this.subscriberExceptionHandler.handleException(e.getCause(), new SubscriberExceptionContext(this, event, wrapper.getSubscriber(), wrapper.getMethod())); + } + catch (Throwable t) { + Logger.getLogger(EventBus.class.getName()).log(Level.SEVERE, String.format("Exception %s thrown while handling exception: %s", t, e.getCause()), t); + } + } + } + + @VisibleForTesting + Set> flattenHierarchy(Class concreteClass) { + try { + return flattenHierarchyCache.getUnchecked(concreteClass); + } + catch (UncheckedExecutionException e) { + throw Throwables.propagate(e.getCause()); + } + } + + static class EventWithSubscriber { + final Object event; + final EventSubscriber subscriber; + + public EventWithSubscriber(Object event, EventSubscriber subscriber) { + this.event = Preconditions.checkNotNull(event); + this.subscriber = Preconditions.checkNotNull(subscriber); + } + } + + private static final class LoggingSubscriberExceptionHandler + implements SubscriberExceptionHandler { + private final Logger logger; + + public LoggingSubscriberExceptionHandler(String identifier) { + String string = String.valueOf(String.valueOf(EventBus.class.getName())); + String string2 = String.valueOf(String.valueOf(Preconditions.checkNotNull(identifier))); + this.logger = Logger.getLogger(new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString()); + } + + @Override + public void handleException(Throwable exception, SubscriberExceptionContext context) { + String string = String.valueOf(String.valueOf(context.getSubscriber())); + String string2 = String.valueOf(String.valueOf(context.getSubscriberMethod())); + this.logger.log(Level.SEVERE, new StringBuilder(30 + string.length() + string2.length()).append("Could not dispatch event: ").append(string).append(" to ").append(string2).toString(), exception.getCause()); + } + } +} diff --git a/src/com/google/common/eventbus/EventSubscriber.java b/src/com/google/common/eventbus/EventSubscriber.java new file mode 100644 index 0000000..ea0fa16 --- /dev/null +++ b/src/com/google/common/eventbus/EventSubscriber.java @@ -0,0 +1,69 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.base.Preconditions; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.annotation.Nullable; + +class EventSubscriber { + private final Object target; + private final Method method; + + EventSubscriber(Object target, Method method) { + Preconditions.checkNotNull(target, "EventSubscriber target cannot be null."); + Preconditions.checkNotNull(method, "EventSubscriber method cannot be null."); + this.target = target; + this.method = method; + method.setAccessible(true); + } + + public void handleEvent(Object event) throws InvocationTargetException { + Preconditions.checkNotNull(event); + try { + this.method.invoke(this.target, event); + } + catch (IllegalArgumentException e) { + String string = String.valueOf(String.valueOf(event)); + throw new Error(new StringBuilder(33 + string.length()).append("Method rejected target/argument: ").append(string).toString(), e); + } + catch (IllegalAccessException e) { + String string = String.valueOf(String.valueOf(event)); + throw new Error(new StringBuilder(28 + string.length()).append("Method became inaccessible: ").append(string).toString(), e); + } + catch (InvocationTargetException e) { + if (e.getCause() instanceof Error) { + throw (Error)e.getCause(); + } + throw e; + } + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.method)); + return new StringBuilder(10 + string.length()).append("[wrapper ").append(string).append("]").toString(); + } + + public int hashCode() { + int PRIME = 31; + return (31 + this.method.hashCode()) * 31 + System.identityHashCode(this.target); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof EventSubscriber) { + EventSubscriber that = (EventSubscriber)obj; + return this.target == that.target && this.method.equals(that.method); + } + return false; + } + + public Object getSubscriber() { + return this.target; + } + + public Method getMethod() { + return this.method; + } +} diff --git a/src/com/google/common/eventbus/Subscribe.java b/src/com/google/common/eventbus/Subscribe.java new file mode 100644 index 0000000..0035945 --- /dev/null +++ b/src/com/google/common/eventbus/Subscribe.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.METHOD}) +@Beta +public @interface Subscribe { +} diff --git a/src/com/google/common/eventbus/SubscriberExceptionContext.java b/src/com/google/common/eventbus/SubscriberExceptionContext.java new file mode 100644 index 0000000..9ebea3e --- /dev/null +++ b/src/com/google/common/eventbus/SubscriberExceptionContext.java @@ -0,0 +1,38 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.base.Preconditions; +import com.google.common.eventbus.EventBus; +import java.lang.reflect.Method; + +public class SubscriberExceptionContext { + private final EventBus eventBus; + private final Object event; + private final Object subscriber; + private final Method subscriberMethod; + + SubscriberExceptionContext(EventBus eventBus, Object event, Object subscriber, Method subscriberMethod) { + this.eventBus = Preconditions.checkNotNull(eventBus); + this.event = Preconditions.checkNotNull(event); + this.subscriber = Preconditions.checkNotNull(subscriber); + this.subscriberMethod = Preconditions.checkNotNull(subscriberMethod); + } + + public EventBus getEventBus() { + return this.eventBus; + } + + public Object getEvent() { + return this.event; + } + + public Object getSubscriber() { + return this.subscriber; + } + + public Method getSubscriberMethod() { + return this.subscriberMethod; + } +} diff --git a/src/com/google/common/eventbus/SubscriberExceptionHandler.java b/src/com/google/common/eventbus/SubscriberExceptionHandler.java new file mode 100644 index 0000000..94b155a --- /dev/null +++ b/src/com/google/common/eventbus/SubscriberExceptionHandler.java @@ -0,0 +1,10 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.eventbus.SubscriberExceptionContext; + +public interface SubscriberExceptionHandler { + public void handleException(Throwable var1, SubscriberExceptionContext var2); +} diff --git a/src/com/google/common/eventbus/SubscriberFindingStrategy.java b/src/com/google/common/eventbus/SubscriberFindingStrategy.java new file mode 100644 index 0000000..c589010 --- /dev/null +++ b/src/com/google/common/eventbus/SubscriberFindingStrategy.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.collect.Multimap; +import com.google.common.eventbus.EventSubscriber; + +interface SubscriberFindingStrategy { + public Multimap, EventSubscriber> findAllSubscribers(Object var1); +} diff --git a/src/com/google/common/eventbus/SynchronizedEventSubscriber.java b/src/com/google/common/eventbus/SynchronizedEventSubscriber.java new file mode 100644 index 0000000..3c4d2d8 --- /dev/null +++ b/src/com/google/common/eventbus/SynchronizedEventSubscriber.java @@ -0,0 +1,26 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.eventbus; + +import com.google.common.eventbus.EventSubscriber; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +final class SynchronizedEventSubscriber +extends EventSubscriber { + public SynchronizedEventSubscriber(Object target, Method method) { + super(target, method); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void handleEvent(Object event) throws InvocationTargetException { + SynchronizedEventSubscriber synchronizedEventSubscriber = this; + synchronized (synchronizedEventSubscriber) { + super.handleEvent(event); + } + } +} diff --git a/src/com/google/common/hash/AbstractByteHasher.java b/src/com/google/common/hash/AbstractByteHasher.java new file mode 100644 index 0000000..4e067b7 --- /dev/null +++ b/src/com/google/common/hash/AbstractByteHasher.java @@ -0,0 +1,94 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractHasher; +import com.google.common.hash.Funnel; +import com.google.common.hash.Hasher; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +abstract class AbstractByteHasher +extends AbstractHasher { + private final ByteBuffer scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); + + AbstractByteHasher() { + } + + protected abstract void update(byte var1); + + protected void update(byte[] b) { + this.update(b, 0, b.length); + } + + protected void update(byte[] b, int off, int len) { + for (int i = off; i < off + len; ++i) { + this.update(b[i]); + } + } + + @Override + public Hasher putByte(byte b) { + this.update(b); + return this; + } + + @Override + public Hasher putBytes(byte[] bytes) { + Preconditions.checkNotNull(bytes); + this.update(bytes); + return this; + } + + @Override + public Hasher putBytes(byte[] bytes, int off, int len) { + Preconditions.checkPositionIndexes(off, off + len, bytes.length); + this.update(bytes, off, len); + return this; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private Hasher update(int bytes) { + try { + this.update(this.scratch.array(), 0, bytes); + } + finally { + this.scratch.clear(); + } + return this; + } + + @Override + public Hasher putShort(short s) { + this.scratch.putShort(s); + return this.update(2); + } + + @Override + public Hasher putInt(int i) { + this.scratch.putInt(i); + return this.update(4); + } + + @Override + public Hasher putLong(long l) { + this.scratch.putLong(l); + return this.update(8); + } + + @Override + public Hasher putChar(char c) { + this.scratch.putChar(c); + return this.update(2); + } + + @Override + public Hasher putObject(T instance, Funnel funnel) { + funnel.funnel(instance, this); + return this; + } +} diff --git a/src/com/google/common/hash/AbstractCompositeHashFunction.java b/src/com/google/common/hash/AbstractCompositeHashFunction.java new file mode 100644 index 0000000..b2bafd8 --- /dev/null +++ b/src/com/google/common/hash/AbstractCompositeHashFunction.java @@ -0,0 +1,146 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.nio.charset.Charset; + +abstract class AbstractCompositeHashFunction +extends AbstractStreamingHashFunction { + final HashFunction[] functions; + private static final long serialVersionUID = 0L; + + AbstractCompositeHashFunction(HashFunction ... functions) { + for (HashFunction function : functions) { + Preconditions.checkNotNull(function); + } + this.functions = functions; + } + + abstract HashCode makeHash(Hasher[] var1); + + @Override + public Hasher newHasher() { + final Hasher[] hashers = new Hasher[this.functions.length]; + for (int i = 0; i < hashers.length; ++i) { + hashers[i] = this.functions[i].newHasher(); + } + return new Hasher(){ + + @Override + public Hasher putByte(byte b) { + for (Hasher hasher : hashers) { + hasher.putByte(b); + } + return this; + } + + @Override + public Hasher putBytes(byte[] bytes) { + for (Hasher hasher : hashers) { + hasher.putBytes(bytes); + } + return this; + } + + @Override + public Hasher putBytes(byte[] bytes, int off, int len) { + for (Hasher hasher : hashers) { + hasher.putBytes(bytes, off, len); + } + return this; + } + + @Override + public Hasher putShort(short s) { + for (Hasher hasher : hashers) { + hasher.putShort(s); + } + return this; + } + + @Override + public Hasher putInt(int i) { + for (Hasher hasher : hashers) { + hasher.putInt(i); + } + return this; + } + + @Override + public Hasher putLong(long l) { + for (Hasher hasher : hashers) { + hasher.putLong(l); + } + return this; + } + + @Override + public Hasher putFloat(float f) { + for (Hasher hasher : hashers) { + hasher.putFloat(f); + } + return this; + } + + @Override + public Hasher putDouble(double d) { + for (Hasher hasher : hashers) { + hasher.putDouble(d); + } + return this; + } + + @Override + public Hasher putBoolean(boolean b) { + for (Hasher hasher : hashers) { + hasher.putBoolean(b); + } + return this; + } + + @Override + public Hasher putChar(char c) { + for (Hasher hasher : hashers) { + hasher.putChar(c); + } + return this; + } + + @Override + public Hasher putUnencodedChars(CharSequence chars) { + for (Hasher hasher : hashers) { + hasher.putUnencodedChars(chars); + } + return this; + } + + @Override + public Hasher putString(CharSequence chars, Charset charset) { + for (Hasher hasher : hashers) { + hasher.putString(chars, charset); + } + return this; + } + + @Override + public Hasher putObject(T instance, Funnel funnel) { + for (Hasher hasher : hashers) { + hasher.putObject(instance, funnel); + } + return this; + } + + @Override + public HashCode hash() { + return AbstractCompositeHashFunction.this.makeHash(hashers); + } + }; + } +} diff --git a/src/com/google/common/hash/AbstractHasher.java b/src/com/google/common/hash/AbstractHasher.java new file mode 100644 index 0000000..03e642c --- /dev/null +++ b/src/com/google/common/hash/AbstractHasher.java @@ -0,0 +1,42 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.hash.Hasher; +import java.nio.charset.Charset; + +abstract class AbstractHasher +implements Hasher { + AbstractHasher() { + } + + @Override + public final Hasher putBoolean(boolean b) { + return this.putByte(b ? (byte)1 : 0); + } + + @Override + public final Hasher putDouble(double d) { + return this.putLong(Double.doubleToRawLongBits(d)); + } + + @Override + public final Hasher putFloat(float f) { + return this.putInt(Float.floatToRawIntBits(f)); + } + + @Override + public Hasher putUnencodedChars(CharSequence charSequence) { + int len = charSequence.length(); + for (int i = 0; i < len; ++i) { + this.putChar(charSequence.charAt(i)); + } + return this; + } + + @Override + public Hasher putString(CharSequence charSequence, Charset charset) { + return this.putBytes(charSequence.toString().getBytes(charset)); + } +} diff --git a/src/com/google/common/hash/AbstractNonStreamingHashFunction.java b/src/com/google/common/hash/AbstractNonStreamingHashFunction.java new file mode 100644 index 0000000..6e466cb --- /dev/null +++ b/src/com/google/common/hash/AbstractNonStreamingHashFunction.java @@ -0,0 +1,156 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractHasher; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; + +abstract class AbstractNonStreamingHashFunction +implements HashFunction { + AbstractNonStreamingHashFunction() { + } + + @Override + public Hasher newHasher() { + return new BufferingHasher(32); + } + + @Override + public Hasher newHasher(int expectedInputSize) { + Preconditions.checkArgument(expectedInputSize >= 0); + return new BufferingHasher(expectedInputSize); + } + + @Override + public HashCode hashObject(T instance, Funnel funnel) { + return this.newHasher().putObject(instance, funnel).hash(); + } + + @Override + public HashCode hashUnencodedChars(CharSequence input) { + int len = input.length(); + Hasher hasher = this.newHasher(len * 2); + for (int i = 0; i < len; ++i) { + hasher.putChar(input.charAt(i)); + } + return hasher.hash(); + } + + @Override + public HashCode hashString(CharSequence input, Charset charset) { + return this.hashBytes(input.toString().getBytes(charset)); + } + + @Override + public HashCode hashInt(int input) { + return this.newHasher(4).putInt(input).hash(); + } + + @Override + public HashCode hashLong(long input) { + return this.newHasher(8).putLong(input).hash(); + } + + @Override + public HashCode hashBytes(byte[] input) { + return this.hashBytes(input, 0, input.length); + } + + private static final class ExposedByteArrayOutputStream + extends ByteArrayOutputStream { + ExposedByteArrayOutputStream(int expectedInputSize) { + super(expectedInputSize); + } + + byte[] byteArray() { + return this.buf; + } + + int length() { + return this.count; + } + } + + private final class BufferingHasher + extends AbstractHasher { + final ExposedByteArrayOutputStream stream; + static final int BOTTOM_BYTE = 255; + + BufferingHasher(int expectedInputSize) { + this.stream = new ExposedByteArrayOutputStream(expectedInputSize); + } + + @Override + public Hasher putByte(byte b) { + this.stream.write(b); + return this; + } + + @Override + public Hasher putBytes(byte[] bytes) { + try { + this.stream.write(bytes); + } + catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + @Override + public Hasher putBytes(byte[] bytes, int off, int len) { + this.stream.write(bytes, off, len); + return this; + } + + @Override + public Hasher putShort(short s) { + this.stream.write(s & 0xFF); + this.stream.write(s >>> 8 & 0xFF); + return this; + } + + @Override + public Hasher putInt(int i) { + this.stream.write(i & 0xFF); + this.stream.write(i >>> 8 & 0xFF); + this.stream.write(i >>> 16 & 0xFF); + this.stream.write(i >>> 24 & 0xFF); + return this; + } + + @Override + public Hasher putLong(long l) { + for (int i = 0; i < 64; i += 8) { + this.stream.write((byte)(l >>> i & 0xFFL)); + } + return this; + } + + @Override + public Hasher putChar(char c) { + this.stream.write(c & 0xFF); + this.stream.write(c >>> 8 & 0xFF); + return this; + } + + @Override + public Hasher putObject(T instance, Funnel funnel) { + funnel.funnel(instance, this); + return this; + } + + @Override + public HashCode hash() { + return AbstractNonStreamingHashFunction.this.hashBytes(this.stream.byteArray(), 0, this.stream.length()); + } + } +} diff --git a/src/com/google/common/hash/AbstractStreamingHashFunction.java b/src/com/google/common/hash/AbstractStreamingHashFunction.java new file mode 100644 index 0000000..22f797e --- /dev/null +++ b/src/com/google/common/hash/AbstractStreamingHashFunction.java @@ -0,0 +1,195 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractHasher; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.Charset; + +abstract class AbstractStreamingHashFunction +implements HashFunction { + AbstractStreamingHashFunction() { + } + + @Override + public HashCode hashObject(T instance, Funnel funnel) { + return this.newHasher().putObject(instance, funnel).hash(); + } + + @Override + public HashCode hashUnencodedChars(CharSequence input) { + return this.newHasher().putUnencodedChars(input).hash(); + } + + @Override + public HashCode hashString(CharSequence input, Charset charset) { + return this.newHasher().putString(input, charset).hash(); + } + + @Override + public HashCode hashInt(int input) { + return this.newHasher().putInt(input).hash(); + } + + @Override + public HashCode hashLong(long input) { + return this.newHasher().putLong(input).hash(); + } + + @Override + public HashCode hashBytes(byte[] input) { + return this.newHasher().putBytes(input).hash(); + } + + @Override + public HashCode hashBytes(byte[] input, int off, int len) { + return this.newHasher().putBytes(input, off, len).hash(); + } + + @Override + public Hasher newHasher(int expectedInputSize) { + Preconditions.checkArgument(expectedInputSize >= 0); + return this.newHasher(); + } + + protected static abstract class AbstractStreamingHasher + extends AbstractHasher { + private final ByteBuffer buffer; + private final int bufferSize; + private final int chunkSize; + + protected AbstractStreamingHasher(int chunkSize) { + this(chunkSize, chunkSize); + } + + protected AbstractStreamingHasher(int chunkSize, int bufferSize) { + Preconditions.checkArgument(bufferSize % chunkSize == 0); + this.buffer = ByteBuffer.allocate(bufferSize + 7).order(ByteOrder.LITTLE_ENDIAN); + this.bufferSize = bufferSize; + this.chunkSize = chunkSize; + } + + protected abstract void process(ByteBuffer var1); + + protected void processRemaining(ByteBuffer bb) { + bb.position(bb.limit()); + bb.limit(this.chunkSize + 7); + while (bb.position() < this.chunkSize) { + bb.putLong(0L); + } + bb.limit(this.chunkSize); + bb.flip(); + this.process(bb); + } + + @Override + public final Hasher putBytes(byte[] bytes) { + return this.putBytes(bytes, 0, bytes.length); + } + + @Override + public final Hasher putBytes(byte[] bytes, int off, int len) { + return this.putBytes(ByteBuffer.wrap(bytes, off, len).order(ByteOrder.LITTLE_ENDIAN)); + } + + private Hasher putBytes(ByteBuffer readBuffer) { + if (readBuffer.remaining() <= this.buffer.remaining()) { + this.buffer.put(readBuffer); + this.munchIfFull(); + return this; + } + int bytesToCopy = this.bufferSize - this.buffer.position(); + for (int i = 0; i < bytesToCopy; ++i) { + this.buffer.put(readBuffer.get()); + } + this.munch(); + while (readBuffer.remaining() >= this.chunkSize) { + this.process(readBuffer); + } + this.buffer.put(readBuffer); + return this; + } + + @Override + public final Hasher putUnencodedChars(CharSequence charSequence) { + for (int i = 0; i < charSequence.length(); ++i) { + this.putChar(charSequence.charAt(i)); + } + return this; + } + + @Override + public final Hasher putByte(byte b) { + this.buffer.put(b); + this.munchIfFull(); + return this; + } + + @Override + public final Hasher putShort(short s) { + this.buffer.putShort(s); + this.munchIfFull(); + return this; + } + + @Override + public final Hasher putChar(char c) { + this.buffer.putChar(c); + this.munchIfFull(); + return this; + } + + @Override + public final Hasher putInt(int i) { + this.buffer.putInt(i); + this.munchIfFull(); + return this; + } + + @Override + public final Hasher putLong(long l) { + this.buffer.putLong(l); + this.munchIfFull(); + return this; + } + + @Override + public final Hasher putObject(T instance, Funnel funnel) { + funnel.funnel(instance, this); + return this; + } + + @Override + public final HashCode hash() { + this.munch(); + this.buffer.flip(); + if (this.buffer.remaining() > 0) { + this.processRemaining(this.buffer); + } + return this.makeHash(); + } + + abstract HashCode makeHash(); + + private void munchIfFull() { + if (this.buffer.remaining() < 8) { + this.munch(); + } + } + + private void munch() { + this.buffer.flip(); + while (this.buffer.remaining() >= this.chunkSize) { + this.process(this.buffer); + } + this.buffer.compact(); + } + } +} diff --git a/src/com/google/common/hash/BloomFilter.java b/src/com/google/common/hash/BloomFilter.java new file mode 100644 index 0000000..98b6418 --- /dev/null +++ b/src/com/google/common/hash/BloomFilter.java @@ -0,0 +1,213 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.hash.BloomFilterStrategies; +import com.google.common.hash.Funnel; +import com.google.common.primitives.SignedBytes; +import com.google.common.primitives.UnsignedBytes; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Serializable; +import javax.annotation.Nullable; + +@Beta +public final class BloomFilter +implements Predicate, +Serializable { + private final BloomFilterStrategies.BitArray bits; + private final int numHashFunctions; + private final Funnel funnel; + private final Strategy strategy; + private static final Strategy DEFAULT_STRATEGY = BloomFilterStrategies.MURMUR128_MITZ_64; + + private BloomFilter(BloomFilterStrategies.BitArray bits, int numHashFunctions, Funnel funnel, Strategy strategy) { + Preconditions.checkArgument(numHashFunctions > 0, "numHashFunctions (%s) must be > 0", numHashFunctions); + Preconditions.checkArgument(numHashFunctions <= 255, "numHashFunctions (%s) must be <= 255", numHashFunctions); + this.bits = Preconditions.checkNotNull(bits); + this.numHashFunctions = numHashFunctions; + this.funnel = Preconditions.checkNotNull(funnel); + this.strategy = Preconditions.checkNotNull(strategy); + } + + public BloomFilter copy() { + return new BloomFilter(this.bits.copy(), this.numHashFunctions, this.funnel, this.strategy); + } + + public boolean mightContain(T object) { + return this.strategy.mightContain(object, this.funnel, this.numHashFunctions, this.bits); + } + + @Override + @Deprecated + public boolean apply(T input) { + return this.mightContain(input); + } + + public boolean put(T object) { + return this.strategy.put(object, this.funnel, this.numHashFunctions, this.bits); + } + + public double expectedFpp() { + return Math.pow((double)this.bits.bitCount() / (double)this.bitSize(), this.numHashFunctions); + } + + @VisibleForTesting + long bitSize() { + return this.bits.bitSize(); + } + + public boolean isCompatible(BloomFilter that) { + Preconditions.checkNotNull(that); + return this != that && this.numHashFunctions == that.numHashFunctions && this.bitSize() == that.bitSize() && this.strategy.equals(that.strategy) && this.funnel.equals(that.funnel); + } + + public void putAll(BloomFilter that) { + Preconditions.checkNotNull(that); + Preconditions.checkArgument(this != that, "Cannot combine a BloomFilter with itself."); + Preconditions.checkArgument(this.numHashFunctions == that.numHashFunctions, "BloomFilters must have the same number of hash functions (%s != %s)", this.numHashFunctions, that.numHashFunctions); + Preconditions.checkArgument(this.bitSize() == that.bitSize(), "BloomFilters must have the same size underlying bit arrays (%s != %s)", this.bitSize(), that.bitSize()); + Preconditions.checkArgument(this.strategy.equals(that.strategy), "BloomFilters must have equal strategies (%s != %s)", this.strategy, that.strategy); + Preconditions.checkArgument(this.funnel.equals(that.funnel), "BloomFilters must have equal funnels (%s != %s)", this.funnel, that.funnel); + this.bits.putAll(that.bits); + } + + @Override + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof BloomFilter) { + BloomFilter that = (BloomFilter)object; + return this.numHashFunctions == that.numHashFunctions && this.funnel.equals(that.funnel) && this.bits.equals(that.bits) && this.strategy.equals(that.strategy); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.numHashFunctions, this.funnel, this.strategy, this.bits); + } + + public static BloomFilter create(Funnel funnel, int expectedInsertions, double fpp) { + return BloomFilter.create(funnel, expectedInsertions, fpp, DEFAULT_STRATEGY); + } + + @VisibleForTesting + static BloomFilter create(Funnel funnel, int expectedInsertions, double fpp, Strategy strategy) { + Preconditions.checkNotNull(funnel); + Preconditions.checkArgument(expectedInsertions >= 0, "Expected insertions (%s) must be >= 0", expectedInsertions); + Preconditions.checkArgument(fpp > 0.0, "False positive probability (%s) must be > 0.0", fpp); + Preconditions.checkArgument(fpp < 1.0, "False positive probability (%s) must be < 1.0", fpp); + Preconditions.checkNotNull(strategy); + if (expectedInsertions == 0) { + expectedInsertions = 1; + } + long numBits = BloomFilter.optimalNumOfBits(expectedInsertions, fpp); + int numHashFunctions = BloomFilter.optimalNumOfHashFunctions(expectedInsertions, numBits); + try { + return new BloomFilter(new BloomFilterStrategies.BitArray(numBits), numHashFunctions, funnel, strategy); + } + catch (IllegalArgumentException e) { + long l = numBits; + throw new IllegalArgumentException(new StringBuilder(57).append("Could not create BloomFilter of ").append(l).append(" bits").toString(), e); + } + } + + public static BloomFilter create(Funnel funnel, int expectedInsertions) { + return BloomFilter.create(funnel, expectedInsertions, 0.03); + } + + @VisibleForTesting + static int optimalNumOfHashFunctions(long n, long m) { + return Math.max(1, (int)Math.round((double)m / (double)n * Math.log(2.0))); + } + + @VisibleForTesting + static long optimalNumOfBits(long n, double p) { + if (p == 0.0) { + p = Double.MIN_VALUE; + } + return (long)((double)(-n) * Math.log(p) / (Math.log(2.0) * Math.log(2.0))); + } + + private Object writeReplace() { + return new SerialForm(this); + } + + public void writeTo(OutputStream out) throws IOException { + DataOutputStream dout = new DataOutputStream(out); + dout.writeByte(SignedBytes.checkedCast(this.strategy.ordinal())); + dout.writeByte(UnsignedBytes.checkedCast(this.numHashFunctions)); + dout.writeInt(this.bits.data.length); + for (long value : this.bits.data) { + dout.writeLong(value); + } + } + + public static BloomFilter readFrom(InputStream in, Funnel funnel) throws IOException { + Preconditions.checkNotNull(in, "InputStream"); + Preconditions.checkNotNull(funnel, "Funnel"); + int strategyOrdinal = -1; + int numHashFunctions = -1; + int dataLength = -1; + try { + DataInputStream din = new DataInputStream(in); + strategyOrdinal = din.readByte(); + numHashFunctions = UnsignedBytes.toInt(din.readByte()); + dataLength = din.readInt(); + BloomFilterStrategies strategy = BloomFilterStrategies.values()[strategyOrdinal]; + long[] data = new long[dataLength]; + for (int i = 0; i < data.length; ++i) { + data[i] = din.readLong(); + } + return new BloomFilter(new BloomFilterStrategies.BitArray(data), numHashFunctions, funnel, strategy); + } + catch (RuntimeException e) { + String string = String.valueOf(String.valueOf("Unable to deserialize BloomFilter from InputStream. strategyOrdinal: ")); + int n = strategyOrdinal; + int n2 = numHashFunctions; + int n3 = dataLength; + IOException ioException = new IOException(new StringBuilder(65 + string.length()).append(string).append(n).append(" numHashFunctions: ").append(n2).append(" dataLength: ").append(n3).toString()); + ioException.initCause(e); + throw ioException; + } + } + + private static class SerialForm + implements Serializable { + final long[] data; + final int numHashFunctions; + final Funnel funnel; + final Strategy strategy; + private static final long serialVersionUID = 1L; + + SerialForm(BloomFilter bf) { + this.data = ((BloomFilter)bf).bits.data; + this.numHashFunctions = ((BloomFilter)bf).numHashFunctions; + this.funnel = ((BloomFilter)bf).funnel; + this.strategy = ((BloomFilter)bf).strategy; + } + + Object readResolve() { + return new BloomFilter(new BloomFilterStrategies.BitArray(this.data), this.numHashFunctions, this.funnel, this.strategy); + } + } + + static interface Strategy + extends Serializable { + public boolean put(T var1, Funnel var2, int var3, BloomFilterStrategies.BitArray var4); + + public boolean mightContain(T var1, Funnel var2, int var3, BloomFilterStrategies.BitArray var4); + + public int ordinal(); + } +} diff --git a/src/com/google/common/hash/BloomFilterStrategies.java b/src/com/google/common/hash/BloomFilterStrategies.java new file mode 100644 index 0000000..9fc9805 --- /dev/null +++ b/src/com/google/common/hash/BloomFilterStrategies.java @@ -0,0 +1,164 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.BloomFilter; +import com.google.common.hash.Funnel; +import com.google.common.hash.Hashing; +import com.google.common.math.LongMath; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.math.RoundingMode; +import java.util.Arrays; + +enum BloomFilterStrategies implements BloomFilter.Strategy +{ + MURMUR128_MITZ_32{ + + @Override + public boolean put(T object, Funnel funnel, int numHashFunctions, BitArray bits) { + long bitSize = bits.bitSize(); + long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong(); + int hash1 = (int)hash64; + int hash2 = (int)(hash64 >>> 32); + boolean bitsChanged = false; + for (int i = 1; i <= numHashFunctions; ++i) { + int combinedHash = hash1 + i * hash2; + if (combinedHash < 0) { + combinedHash ^= 0xFFFFFFFF; + } + bitsChanged |= bits.set((long)combinedHash % bitSize); + } + return bitsChanged; + } + + @Override + public boolean mightContain(T object, Funnel funnel, int numHashFunctions, BitArray bits) { + long bitSize = bits.bitSize(); + long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong(); + int hash1 = (int)hash64; + int hash2 = (int)(hash64 >>> 32); + for (int i = 1; i <= numHashFunctions; ++i) { + int combinedHash = hash1 + i * hash2; + if (combinedHash < 0) { + combinedHash ^= 0xFFFFFFFF; + } + if (bits.get((long)combinedHash % bitSize)) continue; + return false; + } + return true; + } + } + , + MURMUR128_MITZ_64{ + + @Override + public boolean put(T object, Funnel funnel, int numHashFunctions, BitArray bits) { + long bitSize = bits.bitSize(); + byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal(); + long hash1 = this.lowerEight(bytes); + long hash2 = this.upperEight(bytes); + boolean bitsChanged = false; + long combinedHash = hash1; + for (int i = 0; i < numHashFunctions; ++i) { + bitsChanged |= bits.set((combinedHash & Long.MAX_VALUE) % bitSize); + combinedHash += hash2; + } + return bitsChanged; + } + + @Override + public boolean mightContain(T object, Funnel funnel, int numHashFunctions, BitArray bits) { + long bitSize = bits.bitSize(); + byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal(); + long hash1 = this.lowerEight(bytes); + long hash2 = this.upperEight(bytes); + long combinedHash = hash1; + for (int i = 0; i < numHashFunctions; ++i) { + if (!bits.get((combinedHash & Long.MAX_VALUE) % bitSize)) { + return false; + } + combinedHash += hash2; + } + return true; + } + + private long lowerEight(byte[] bytes) { + return Longs.fromBytes(bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]); + } + + private long upperEight(byte[] bytes) { + return Longs.fromBytes(bytes[15], bytes[14], bytes[13], bytes[12], bytes[11], bytes[10], bytes[9], bytes[8]); + } + }; + + + static final class BitArray { + final long[] data; + long bitCount; + + BitArray(long bits) { + this(new long[Ints.checkedCast(LongMath.divide(bits, 64L, RoundingMode.CEILING))]); + } + + BitArray(long[] data) { + Preconditions.checkArgument(data.length > 0, "data length is zero!"); + this.data = data; + long bitCount = 0L; + for (long value : data) { + bitCount += (long)Long.bitCount(value); + } + this.bitCount = bitCount; + } + + boolean set(long index) { + if (!this.get(index)) { + int n = (int)(index >>> 6); + this.data[n] = this.data[n] | 1L << (int)index; + ++this.bitCount; + return true; + } + return false; + } + + boolean get(long index) { + return (this.data[(int)(index >>> 6)] & 1L << (int)index) != 0L; + } + + long bitSize() { + return (long)this.data.length * 64L; + } + + long bitCount() { + return this.bitCount; + } + + BitArray copy() { + return new BitArray((long[])this.data.clone()); + } + + void putAll(BitArray array) { + Preconditions.checkArgument(this.data.length == array.data.length, "BitArrays must be of equal length (%s != %s)", this.data.length, array.data.length); + this.bitCount = 0L; + for (int i = 0; i < this.data.length; ++i) { + int n = i; + this.data[n] = this.data[n] | array.data[i]; + this.bitCount += (long)Long.bitCount(this.data[i]); + } + } + + public boolean equals(Object o) { + if (o instanceof BitArray) { + BitArray bitArray = (BitArray)o; + return Arrays.equals(this.data, bitArray.data); + } + return false; + } + + public int hashCode() { + return Arrays.hashCode(this.data); + } + } +} diff --git a/src/com/google/common/hash/ChecksumHashFunction.java b/src/com/google/common/hash/ChecksumHashFunction.java new file mode 100644 index 0000000..c89fdea --- /dev/null +++ b/src/com/google/common/hash/ChecksumHashFunction.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.hash.AbstractByteHasher; +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import java.io.Serializable; +import java.util.zip.Checksum; + +final class ChecksumHashFunction +extends AbstractStreamingHashFunction +implements Serializable { + private final Supplier checksumSupplier; + private final int bits; + private final String toString; + private static final long serialVersionUID = 0L; + + ChecksumHashFunction(Supplier checksumSupplier, int bits, String toString) { + this.checksumSupplier = Preconditions.checkNotNull(checksumSupplier); + Preconditions.checkArgument(bits == 32 || bits == 64, "bits (%s) must be either 32 or 64", bits); + this.bits = bits; + this.toString = Preconditions.checkNotNull(toString); + } + + @Override + public int bits() { + return this.bits; + } + + @Override + public Hasher newHasher() { + return new ChecksumHasher(this.checksumSupplier.get()); + } + + public String toString() { + return this.toString; + } + + private final class ChecksumHasher + extends AbstractByteHasher { + private final Checksum checksum; + + private ChecksumHasher(Checksum checksum) { + this.checksum = Preconditions.checkNotNull(checksum); + } + + @Override + protected void update(byte b) { + this.checksum.update(b); + } + + @Override + protected void update(byte[] bytes, int off, int len) { + this.checksum.update(bytes, off, len); + } + + @Override + public HashCode hash() { + long value = this.checksum.getValue(); + if (ChecksumHashFunction.this.bits == 32) { + return HashCode.fromInt((int)value); + } + return HashCode.fromLong(value); + } + } +} diff --git a/src/com/google/common/hash/Crc32cHashFunction.java b/src/com/google/common/hash/Crc32cHashFunction.java new file mode 100644 index 0000000..62db933 --- /dev/null +++ b/src/com/google/common/hash/Crc32cHashFunction.java @@ -0,0 +1,49 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.hash.AbstractByteHasher; +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; + +final class Crc32cHashFunction +extends AbstractStreamingHashFunction { + Crc32cHashFunction() { + } + + @Override + public int bits() { + return 32; + } + + @Override + public Hasher newHasher() { + return new Crc32cHasher(); + } + + public String toString() { + return "Hashing.crc32c()"; + } + + static final class Crc32cHasher + extends AbstractByteHasher { + static final int[] CRC_TABLE = new int[]{0, -227835133, -516198153, 324072436, -946170081, 904991772, 648144872, -724933397, -1965467441, 2024987596, 1809983544, -1719030981, 1296289744, -1087877933, -1401372889, 1578318884, 274646895, -499825556, -244992104, 51262619, -675000208, 632279923, 922689671, -996891772, -1702387808, 1760304291, 2075979607, -1982370732, 1562183871, -1351185476, -1138329528, 1313733451, 549293790, -757723683, -1048117719, 871202090, -416867903, 357341890, 102525238, -193467851, -1436232175, 1477399826, 1264559846, -1187764763, 1845379342, -1617575411, -1933233671, 2125378298, 820201905, -1031222606, -774358714, 598981189, -143008082, 85089709, 373468761, -467063462, -1170599554, 1213305469, 1526817161, -1452612982, 2107672161, -1882520222, -1667500394, 1861252501, 1098587580, -1290756417, -1606390453, 1378610760, -2032039261, 1955203488, 1742404180, -1783531177, -878557837, 969524848, 714683780, -655182201, 205050476, -28094097, -318528869, 526918040, 1361435347, -1555146288, -1340167644, 1114974503, -1765847604, 1691668175, 2005155131, -2047885768, -604208612, 697762079, 986182379, -928222744, 476452099, -301099520, -44210700, 255256311, 1640403810, -1817374623, -2130844779, 1922457750, -1503918979, 1412925310, 1197962378, -1257441399, -350237779, 427051182, 170179418, -129025959, 746937522, -554770511, -843174843, 1070968646, 1905808397, -2081171698, -1868356358, 1657317369, -1241332974, 1147748369, 1463399397, -1521340186, -79622974, 153784257, 444234805, -401473738, 1021025245, -827320098, -572462294, 797665321, -2097792136, 1889384571, 1674398607, -1851340660, 1164749927, -1224265884, -1537745776, 1446797203, 137323447, -96149324, -384560320, 461344835, -810158936, 1037989803, 781091935, -588970148, -1834419177, 1623424788, 1939049696, -2114449437, 1429367560, -1487280117, -1274471425, 1180866812, 410100952, -367384613, -112536529, 186734380, -538233913, 763408580, 1053836080, -860110797, -1572096602, 1344288421, 1131464017, -1323612590, 1708204729, -1749376582, -2065018290, 1988219213, 680717673, -621187478, -911630946, 1002577565, -284657034, 493091189, 238226049, -61306494, -1307217207, 1082061258, 1395524158, -1589280451, 1972364758, -2015074603, -1800104671, 1725896226, 952904198, -894981883, -638100751, 731699698, -11092711, 222117402, 510512622, -335130899, -1014159676, 837199303, 582374963, -790768336, 68661723, -159632680, -450051796, 390545967, 1230274059, -1153434360, -1469116676, 1510247935, -1899042540, 2091215383, 1878366691, -1650582816, -741088853, 565732008, 854102364, -1065151905, 340358836, -433916489, -177076669, 119113024, 1493875044, -1419691417, -1204696685, 1247431312, -1634718085, 1828433272, 2141937292, -1916740209, -483350502, 291187481, 34330861, -262120466, 615137029, -691946490, -980332558, 939183345, 1776939221, -1685949482, -1999470558, 2058945313, -1368168502, 1545135305, 1330124605, -1121741762, -210866315, 17165430, 307568514, -532767615, 888469610, -962626711, -707819363, 665062302, 2042050490, -1948470087, -1735637171, 1793573966, -1104306011, 1279665062, 1595330642, -1384295599}; + private int crc = 0; + + Crc32cHasher() { + } + + @Override + public void update(byte b) { + this.crc ^= 0xFFFFFFFF; + this.crc = ~(this.crc >>> 8 ^ CRC_TABLE[(this.crc ^ b) & 0xFF]); + } + + @Override + public HashCode hash() { + return HashCode.fromInt(this.crc); + } + } +} diff --git a/src/com/google/common/hash/Funnel.java b/src/com/google/common/hash/Funnel.java new file mode 100644 index 0000000..b7e9380 --- /dev/null +++ b/src/com/google/common/hash/Funnel.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.hash.PrimitiveSink; +import java.io.Serializable; + +@Beta +public interface Funnel +extends Serializable { + public void funnel(T var1, PrimitiveSink var2); +} diff --git a/src/com/google/common/hash/Funnels.java b/src/com/google/common/hash/Funnels.java new file mode 100644 index 0000000..b97a525 --- /dev/null +++ b/src/com/google/common/hash/Funnels.java @@ -0,0 +1,220 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.hash.Funnel; +import com.google.common.hash.PrimitiveSink; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.Charset; +import javax.annotation.Nullable; + +@Beta +public final class Funnels { + private Funnels() { + } + + public static Funnel byteArrayFunnel() { + return ByteArrayFunnel.INSTANCE; + } + + public static Funnel unencodedCharsFunnel() { + return UnencodedCharsFunnel.INSTANCE; + } + + public static Funnel stringFunnel(Charset charset) { + return new StringCharsetFunnel(charset); + } + + public static Funnel integerFunnel() { + return IntegerFunnel.INSTANCE; + } + + public static Funnel> sequentialFunnel(Funnel elementFunnel) { + return new SequentialFunnel(elementFunnel); + } + + public static Funnel longFunnel() { + return LongFunnel.INSTANCE; + } + + public static OutputStream asOutputStream(PrimitiveSink sink) { + return new SinkAsStream(sink); + } + + private static class SinkAsStream + extends OutputStream { + final PrimitiveSink sink; + + SinkAsStream(PrimitiveSink sink) { + this.sink = Preconditions.checkNotNull(sink); + } + + @Override + public void write(int b) { + this.sink.putByte((byte)b); + } + + @Override + public void write(byte[] bytes) { + this.sink.putBytes(bytes); + } + + @Override + public void write(byte[] bytes, int off, int len) { + this.sink.putBytes(bytes, off, len); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.sink)); + return new StringBuilder(24 + string.length()).append("Funnels.asOutputStream(").append(string).append(")").toString(); + } + } + + private static enum LongFunnel implements Funnel + { + INSTANCE; + + + @Override + public void funnel(Long from, PrimitiveSink into) { + into.putLong(from); + } + + public String toString() { + return "Funnels.longFunnel()"; + } + } + + private static class SequentialFunnel + implements Funnel>, + Serializable { + private final Funnel elementFunnel; + + SequentialFunnel(Funnel elementFunnel) { + this.elementFunnel = Preconditions.checkNotNull(elementFunnel); + } + + @Override + public void funnel(Iterable from, PrimitiveSink into) { + for (E e : from) { + this.elementFunnel.funnel(e, into); + } + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.elementFunnel)); + return new StringBuilder(26 + string.length()).append("Funnels.sequentialFunnel(").append(string).append(")").toString(); + } + + public boolean equals(@Nullable Object o) { + if (o instanceof SequentialFunnel) { + SequentialFunnel funnel = (SequentialFunnel)o; + return this.elementFunnel.equals(funnel.elementFunnel); + } + return false; + } + + public int hashCode() { + return SequentialFunnel.class.hashCode() ^ this.elementFunnel.hashCode(); + } + } + + private static enum IntegerFunnel implements Funnel + { + INSTANCE; + + + @Override + public void funnel(Integer from, PrimitiveSink into) { + into.putInt(from); + } + + public String toString() { + return "Funnels.integerFunnel()"; + } + } + + private static class StringCharsetFunnel + implements Funnel, + Serializable { + private final Charset charset; + + StringCharsetFunnel(Charset charset) { + this.charset = Preconditions.checkNotNull(charset); + } + + @Override + public void funnel(CharSequence from, PrimitiveSink into) { + into.putString(from, this.charset); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.charset.name())); + return new StringBuilder(22 + string.length()).append("Funnels.stringFunnel(").append(string).append(")").toString(); + } + + public boolean equals(@Nullable Object o) { + if (o instanceof StringCharsetFunnel) { + StringCharsetFunnel funnel = (StringCharsetFunnel)o; + return this.charset.equals(funnel.charset); + } + return false; + } + + public int hashCode() { + return StringCharsetFunnel.class.hashCode() ^ this.charset.hashCode(); + } + + Object writeReplace() { + return new SerializedForm(this.charset); + } + + private static class SerializedForm + implements Serializable { + private final String charsetCanonicalName; + private static final long serialVersionUID = 0L; + + SerializedForm(Charset charset) { + this.charsetCanonicalName = charset.name(); + } + + private Object readResolve() { + return Funnels.stringFunnel(Charset.forName(this.charsetCanonicalName)); + } + } + } + + private static enum UnencodedCharsFunnel implements Funnel + { + INSTANCE; + + + @Override + public void funnel(CharSequence from, PrimitiveSink into) { + into.putUnencodedChars(from); + } + + public String toString() { + return "Funnels.unencodedCharsFunnel()"; + } + } + + private static enum ByteArrayFunnel implements Funnel + { + INSTANCE; + + + @Override + public void funnel(byte[] from, PrimitiveSink into) { + into.putBytes(from); + } + + public String toString() { + return "Funnels.byteArrayFunnel()"; + } + } +} diff --git a/src/com/google/common/hash/HashCode.java b/src/com/google/common/hash/HashCode.java new file mode 100644 index 0000000..58505ab --- /dev/null +++ b/src/com/google/common/hash/HashCode.java @@ -0,0 +1,267 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import com.google.common.primitives.UnsignedInts; +import java.io.Serializable; +import java.security.MessageDigest; +import javax.annotation.Nullable; + +@Beta +public abstract class HashCode { + private static final char[] hexDigits = "0123456789abcdef".toCharArray(); + + HashCode() { + } + + public abstract int bits(); + + public abstract int asInt(); + + public abstract long asLong(); + + public abstract long padToLong(); + + public abstract byte[] asBytes(); + + public int writeBytesTo(byte[] dest, int offset, int maxLength) { + maxLength = Ints.min(maxLength, this.bits() / 8); + Preconditions.checkPositionIndexes(offset, offset + maxLength, dest.length); + this.writeBytesToImpl(dest, offset, maxLength); + return maxLength; + } + + abstract void writeBytesToImpl(byte[] var1, int var2, int var3); + + byte[] getBytesInternal() { + return this.asBytes(); + } + + abstract boolean equalsSameBits(HashCode var1); + + public static HashCode fromInt(int hash) { + return new IntHashCode(hash); + } + + public static HashCode fromLong(long hash) { + return new LongHashCode(hash); + } + + public static HashCode fromBytes(byte[] bytes) { + Preconditions.checkArgument(bytes.length >= 1, "A HashCode must contain at least 1 byte."); + return HashCode.fromBytesNoCopy((byte[])bytes.clone()); + } + + static HashCode fromBytesNoCopy(byte[] bytes) { + return new BytesHashCode(bytes); + } + + public static HashCode fromString(String string) { + Preconditions.checkArgument(string.length() >= 2, "input string (%s) must have at least 2 characters", string); + Preconditions.checkArgument(string.length() % 2 == 0, "input string (%s) must have an even number of characters", string); + byte[] bytes = new byte[string.length() / 2]; + for (int i = 0; i < string.length(); i += 2) { + int ch1 = HashCode.decode(string.charAt(i)) << 4; + int ch2 = HashCode.decode(string.charAt(i + 1)); + bytes[i / 2] = (byte)(ch1 + ch2); + } + return HashCode.fromBytesNoCopy(bytes); + } + + private static int decode(char ch) { + if (ch >= '0' && ch <= '9') { + return ch - 48; + } + if (ch >= 'a' && ch <= 'f') { + return ch - 97 + 10; + } + char c = ch; + throw new IllegalArgumentException(new StringBuilder(32).append("Illegal hexadecimal character: ").append(c).toString()); + } + + public final boolean equals(@Nullable Object object) { + if (object instanceof HashCode) { + HashCode that = (HashCode)object; + return this.bits() == that.bits() && this.equalsSameBits(that); + } + return false; + } + + public final int hashCode() { + if (this.bits() >= 32) { + return this.asInt(); + } + byte[] bytes = this.asBytes(); + int val = bytes[0] & 0xFF; + for (int i = 1; i < bytes.length; ++i) { + val |= (bytes[i] & 0xFF) << i * 8; + } + return val; + } + + public final String toString() { + byte[] bytes = this.asBytes(); + StringBuilder sb = new StringBuilder(2 * bytes.length); + for (byte b : bytes) { + sb.append(hexDigits[b >> 4 & 0xF]).append(hexDigits[b & 0xF]); + } + return sb.toString(); + } + + private static final class BytesHashCode + extends HashCode + implements Serializable { + final byte[] bytes; + private static final long serialVersionUID = 0L; + + BytesHashCode(byte[] bytes) { + this.bytes = Preconditions.checkNotNull(bytes); + } + + @Override + public int bits() { + return this.bytes.length * 8; + } + + @Override + public byte[] asBytes() { + return (byte[])this.bytes.clone(); + } + + @Override + public int asInt() { + Preconditions.checkState(this.bytes.length >= 4, "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).", this.bytes.length); + return this.bytes[0] & 0xFF | (this.bytes[1] & 0xFF) << 8 | (this.bytes[2] & 0xFF) << 16 | (this.bytes[3] & 0xFF) << 24; + } + + @Override + public long asLong() { + Preconditions.checkState(this.bytes.length >= 8, "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).", this.bytes.length); + return this.padToLong(); + } + + @Override + public long padToLong() { + long retVal = this.bytes[0] & 0xFF; + for (int i = 1; i < Math.min(this.bytes.length, 8); ++i) { + retVal |= ((long)this.bytes[i] & 0xFFL) << i * 8; + } + return retVal; + } + + @Override + void writeBytesToImpl(byte[] dest, int offset, int maxLength) { + System.arraycopy(this.bytes, 0, dest, offset, maxLength); + } + + @Override + byte[] getBytesInternal() { + return this.bytes; + } + + @Override + boolean equalsSameBits(HashCode that) { + return MessageDigest.isEqual(this.bytes, that.getBytesInternal()); + } + } + + private static final class LongHashCode + extends HashCode + implements Serializable { + final long hash; + private static final long serialVersionUID = 0L; + + LongHashCode(long hash) { + this.hash = hash; + } + + @Override + public int bits() { + return 64; + } + + @Override + public byte[] asBytes() { + return new byte[]{(byte)this.hash, (byte)(this.hash >> 8), (byte)(this.hash >> 16), (byte)(this.hash >> 24), (byte)(this.hash >> 32), (byte)(this.hash >> 40), (byte)(this.hash >> 48), (byte)(this.hash >> 56)}; + } + + @Override + public int asInt() { + return (int)this.hash; + } + + @Override + public long asLong() { + return this.hash; + } + + @Override + public long padToLong() { + return this.hash; + } + + @Override + void writeBytesToImpl(byte[] dest, int offset, int maxLength) { + for (int i = 0; i < maxLength; ++i) { + dest[offset + i] = (byte)(this.hash >> i * 8); + } + } + + @Override + boolean equalsSameBits(HashCode that) { + return this.hash == that.asLong(); + } + } + + private static final class IntHashCode + extends HashCode + implements Serializable { + final int hash; + private static final long serialVersionUID = 0L; + + IntHashCode(int hash) { + this.hash = hash; + } + + @Override + public int bits() { + return 32; + } + + @Override + public byte[] asBytes() { + return new byte[]{(byte)this.hash, (byte)(this.hash >> 8), (byte)(this.hash >> 16), (byte)(this.hash >> 24)}; + } + + @Override + public int asInt() { + return this.hash; + } + + @Override + public long asLong() { + throw new IllegalStateException("this HashCode only has 32 bits; cannot create a long"); + } + + @Override + public long padToLong() { + return UnsignedInts.toLong(this.hash); + } + + @Override + void writeBytesToImpl(byte[] dest, int offset, int maxLength) { + for (int i = 0; i < maxLength; ++i) { + dest[offset + i] = (byte)(this.hash >> i * 8); + } + } + + @Override + boolean equalsSameBits(HashCode that) { + return this.hash == that.asInt(); + } + } +} diff --git a/src/com/google/common/hash/HashFunction.java b/src/com/google/common/hash/HashFunction.java new file mode 100644 index 0000000..44dee8a --- /dev/null +++ b/src/com/google/common/hash/HashFunction.java @@ -0,0 +1,33 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import java.nio.charset.Charset; + +@Beta +public interface HashFunction { + public Hasher newHasher(); + + public Hasher newHasher(int var1); + + public HashCode hashInt(int var1); + + public HashCode hashLong(long var1); + + public HashCode hashBytes(byte[] var1); + + public HashCode hashBytes(byte[] var1, int var2, int var3); + + public HashCode hashUnencodedChars(CharSequence var1); + + public HashCode hashString(CharSequence var1, Charset var2); + + public HashCode hashObject(T var1, Funnel var2); + + public int bits(); +} diff --git a/src/com/google/common/hash/Hasher.java b/src/com/google/common/hash/Hasher.java new file mode 100644 index 0000000..3bee8c8 --- /dev/null +++ b/src/com/google/common/hash/Hasher.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.PrimitiveSink; +import java.nio.charset.Charset; + +@Beta +public interface Hasher +extends PrimitiveSink { + @Override + public Hasher putByte(byte var1); + + @Override + public Hasher putBytes(byte[] var1); + + @Override + public Hasher putBytes(byte[] var1, int var2, int var3); + + @Override + public Hasher putShort(short var1); + + @Override + public Hasher putInt(int var1); + + @Override + public Hasher putLong(long var1); + + @Override + public Hasher putFloat(float var1); + + @Override + public Hasher putDouble(double var1); + + @Override + public Hasher putBoolean(boolean var1); + + @Override + public Hasher putChar(char var1); + + @Override + public Hasher putUnencodedChars(CharSequence var1); + + @Override + public Hasher putString(CharSequence var1, Charset var2); + + public Hasher putObject(T var1, Funnel var2); + + public HashCode hash(); +} diff --git a/src/com/google/common/hash/Hashing.java b/src/com/google/common/hash/Hashing.java new file mode 100644 index 0000000..b371e1b --- /dev/null +++ b/src/com/google/common/hash/Hashing.java @@ -0,0 +1,331 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.hash.AbstractCompositeHashFunction; +import com.google.common.hash.ChecksumHashFunction; +import com.google.common.hash.Crc32cHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import com.google.common.hash.MessageDigestHashFunction; +import com.google.common.hash.Murmur3_128HashFunction; +import com.google.common.hash.Murmur3_32HashFunction; +import com.google.common.hash.SipHashFunction; +import java.util.Iterator; +import java.util.zip.Adler32; +import java.util.zip.CRC32; +import java.util.zip.Checksum; +import javax.annotation.Nullable; + +@Beta +public final class Hashing { + private static final int GOOD_FAST_HASH_SEED = (int)System.currentTimeMillis(); + + public static HashFunction goodFastHash(int minimumBits) { + int bits = Hashing.checkPositiveAndMakeMultipleOf32(minimumBits); + if (bits == 32) { + return Murmur3_32Holder.GOOD_FAST_HASH_FUNCTION_32; + } + if (bits <= 128) { + return Murmur3_128Holder.GOOD_FAST_HASH_FUNCTION_128; + } + int hashFunctionsNeeded = (bits + 127) / 128; + HashFunction[] hashFunctions = new HashFunction[hashFunctionsNeeded]; + hashFunctions[0] = Murmur3_128Holder.GOOD_FAST_HASH_FUNCTION_128; + int seed = GOOD_FAST_HASH_SEED; + for (int i = 1; i < hashFunctionsNeeded; ++i) { + hashFunctions[i] = Hashing.murmur3_128(seed += 1500450271); + } + return new ConcatenatedHashFunction(hashFunctions); + } + + public static HashFunction murmur3_32(int seed) { + return new Murmur3_32HashFunction(seed); + } + + public static HashFunction murmur3_32() { + return Murmur3_32Holder.MURMUR3_32; + } + + public static HashFunction murmur3_128(int seed) { + return new Murmur3_128HashFunction(seed); + } + + public static HashFunction murmur3_128() { + return Murmur3_128Holder.MURMUR3_128; + } + + public static HashFunction sipHash24() { + return SipHash24Holder.SIP_HASH_24; + } + + public static HashFunction sipHash24(long k0, long k1) { + return new SipHashFunction(2, 4, k0, k1); + } + + public static HashFunction md5() { + return Md5Holder.MD5; + } + + public static HashFunction sha1() { + return Sha1Holder.SHA_1; + } + + public static HashFunction sha256() { + return Sha256Holder.SHA_256; + } + + public static HashFunction sha512() { + return Sha512Holder.SHA_512; + } + + public static HashFunction crc32c() { + return Crc32cHolder.CRC_32_C; + } + + public static HashFunction crc32() { + return Crc32Holder.CRC_32; + } + + public static HashFunction adler32() { + return Adler32Holder.ADLER_32; + } + + private static HashFunction checksumHashFunction(ChecksumType type, String toString) { + return new ChecksumHashFunction(type, type.bits, toString); + } + + public static int consistentHash(HashCode hashCode, int buckets) { + return Hashing.consistentHash(hashCode.padToLong(), buckets); + } + + public static int consistentHash(long input, int buckets) { + int next; + Preconditions.checkArgument(buckets > 0, "buckets must be positive: %s", buckets); + LinearCongruentialGenerator generator = new LinearCongruentialGenerator(input); + int candidate = 0; + while ((next = (int)((double)(candidate + 1) / generator.nextDouble())) >= 0 && next < buckets) { + candidate = next; + } + return candidate; + } + + public static HashCode combineOrdered(Iterable hashCodes) { + Iterator iterator = hashCodes.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "Must be at least 1 hash code to combine."); + int bits = iterator.next().bits(); + byte[] resultBytes = new byte[bits / 8]; + for (HashCode hashCode : hashCodes) { + byte[] nextBytes = hashCode.asBytes(); + Preconditions.checkArgument(nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length."); + for (int i = 0; i < nextBytes.length; ++i) { + resultBytes[i] = (byte)(resultBytes[i] * 37 ^ nextBytes[i]); + } + } + return HashCode.fromBytesNoCopy(resultBytes); + } + + public static HashCode combineUnordered(Iterable hashCodes) { + Iterator iterator = hashCodes.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "Must be at least 1 hash code to combine."); + byte[] resultBytes = new byte[iterator.next().bits() / 8]; + for (HashCode hashCode : hashCodes) { + byte[] nextBytes = hashCode.asBytes(); + Preconditions.checkArgument(nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length."); + for (int i = 0; i < nextBytes.length; ++i) { + int n = i; + resultBytes[n] = (byte)(resultBytes[n] + nextBytes[i]); + } + } + return HashCode.fromBytesNoCopy(resultBytes); + } + + static int checkPositiveAndMakeMultipleOf32(int bits) { + Preconditions.checkArgument(bits > 0, "Number of bits must be positive"); + return bits + 31 & 0xFFFFFFE0; + } + + private Hashing() { + } + + static /* synthetic */ int access$000() { + return GOOD_FAST_HASH_SEED; + } + + static /* synthetic */ HashFunction access$100(ChecksumType x0, String x1) { + return Hashing.checksumHashFunction(x0, x1); + } + + private static final class LinearCongruentialGenerator { + private long state; + + public LinearCongruentialGenerator(long seed) { + this.state = seed; + } + + public double nextDouble() { + this.state = 2862933555777941757L * this.state + 1L; + return (double)((int)(this.state >>> 33) + 1) / 2.147483648E9; + } + } + + @VisibleForTesting + static final class ConcatenatedHashFunction + extends AbstractCompositeHashFunction { + private final int bits; + + ConcatenatedHashFunction(HashFunction ... functions) { + super(functions); + int bitSum = 0; + for (HashFunction function : functions) { + bitSum += function.bits(); + } + this.bits = bitSum; + } + + @Override + HashCode makeHash(Hasher[] hashers) { + byte[] bytes = new byte[this.bits / 8]; + int i = 0; + for (Hasher hasher : hashers) { + HashCode newHash = hasher.hash(); + i += newHash.writeBytesTo(bytes, i, newHash.bits() / 8); + } + return HashCode.fromBytesNoCopy(bytes); + } + + @Override + public int bits() { + return this.bits; + } + + public boolean equals(@Nullable Object object) { + if (object instanceof ConcatenatedHashFunction) { + ConcatenatedHashFunction other = (ConcatenatedHashFunction)object; + if (this.bits != other.bits || this.functions.length != other.functions.length) { + return false; + } + for (int i = 0; i < this.functions.length; ++i) { + if (this.functions[i].equals(other.functions[i])) continue; + return false; + } + return true; + } + return false; + } + + public int hashCode() { + int hash = this.bits; + for (HashFunction function : this.functions) { + hash ^= function.hashCode(); + } + return hash; + } + } + + static enum ChecksumType implements Supplier + { + CRC_32(32){ + + @Override + public Checksum get() { + return new CRC32(); + } + } + , + ADLER_32(32){ + + @Override + public Checksum get() { + return new Adler32(); + } + }; + + private final int bits; + + private ChecksumType(int bits) { + this.bits = bits; + } + + @Override + public abstract Checksum get(); + } + + private static class Adler32Holder { + static final HashFunction ADLER_32 = Hashing.access$100(ChecksumType.ADLER_32, "Hashing.adler32()"); + + private Adler32Holder() { + } + } + + private static class Crc32Holder { + static final HashFunction CRC_32 = Hashing.access$100(ChecksumType.CRC_32, "Hashing.crc32()"); + + private Crc32Holder() { + } + } + + private static final class Crc32cHolder { + static final HashFunction CRC_32_C = new Crc32cHashFunction(); + + private Crc32cHolder() { + } + } + + private static class Sha512Holder { + static final HashFunction SHA_512 = new MessageDigestHashFunction("SHA-512", "Hashing.sha512()"); + + private Sha512Holder() { + } + } + + private static class Sha256Holder { + static final HashFunction SHA_256 = new MessageDigestHashFunction("SHA-256", "Hashing.sha256()"); + + private Sha256Holder() { + } + } + + private static class Sha1Holder { + static final HashFunction SHA_1 = new MessageDigestHashFunction("SHA-1", "Hashing.sha1()"); + + private Sha1Holder() { + } + } + + private static class Md5Holder { + static final HashFunction MD5 = new MessageDigestHashFunction("MD5", "Hashing.md5()"); + + private Md5Holder() { + } + } + + private static class SipHash24Holder { + static final HashFunction SIP_HASH_24 = new SipHashFunction(2, 4, 506097522914230528L, 1084818905618843912L); + + private SipHash24Holder() { + } + } + + private static class Murmur3_128Holder { + static final HashFunction MURMUR3_128 = new Murmur3_128HashFunction(0); + static final HashFunction GOOD_FAST_HASH_FUNCTION_128 = Hashing.murmur3_128(Hashing.access$000()); + + private Murmur3_128Holder() { + } + } + + private static class Murmur3_32Holder { + static final HashFunction MURMUR3_32 = new Murmur3_32HashFunction(0); + static final HashFunction GOOD_FAST_HASH_FUNCTION_32 = Hashing.murmur3_32(Hashing.access$000()); + + private Murmur3_32Holder() { + } + } +} diff --git a/src/com/google/common/hash/HashingInputStream.java b/src/com/google/common/hash/HashingInputStream.java new file mode 100644 index 0000000..2bf04b3 --- /dev/null +++ b/src/com/google/common/hash/HashingInputStream.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +@Beta +public final class HashingInputStream +extends FilterInputStream { + private final Hasher hasher; + + public HashingInputStream(HashFunction hashFunction, InputStream in) { + super(Preconditions.checkNotNull(in)); + this.hasher = Preconditions.checkNotNull(hashFunction.newHasher()); + } + + @Override + public int read() throws IOException { + int b = this.in.read(); + if (b != -1) { + this.hasher.putByte((byte)b); + } + return b; + } + + @Override + public int read(byte[] bytes, int off, int len) throws IOException { + int numOfBytesRead = this.in.read(bytes, off, len); + if (numOfBytesRead != -1) { + this.hasher.putBytes(bytes, off, numOfBytesRead); + } + return numOfBytesRead; + } + + @Override + public boolean markSupported() { + return false; + } + + @Override + public void mark(int readlimit) { + } + + @Override + public void reset() throws IOException { + throw new IOException("reset not supported"); + } + + public HashCode hash() { + return this.hasher.hash(); + } +} diff --git a/src/com/google/common/hash/HashingOutputStream.java b/src/com/google/common/hash/HashingOutputStream.java new file mode 100644 index 0000000..b9c56bc --- /dev/null +++ b/src/com/google/common/hash/HashingOutputStream.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +@Beta +public final class HashingOutputStream +extends FilterOutputStream { + private final Hasher hasher; + + public HashingOutputStream(HashFunction hashFunction, OutputStream out) { + super(Preconditions.checkNotNull(out)); + this.hasher = Preconditions.checkNotNull(hashFunction.newHasher()); + } + + @Override + public void write(int b) throws IOException { + this.hasher.putByte((byte)b); + this.out.write(b); + } + + @Override + public void write(byte[] bytes, int off, int len) throws IOException { + this.hasher.putBytes(bytes, off, len); + this.out.write(bytes, off, len); + } + + public HashCode hash() { + return this.hasher.hash(); + } + + @Override + public void close() throws IOException { + this.out.close(); + } +} diff --git a/src/com/google/common/hash/MessageDigestHashFunction.java b/src/com/google/common/hash/MessageDigestHashFunction.java new file mode 100644 index 0000000..2f6526b --- /dev/null +++ b/src/com/google/common/hash/MessageDigestHashFunction.java @@ -0,0 +1,143 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractByteHasher; +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +final class MessageDigestHashFunction +extends AbstractStreamingHashFunction +implements Serializable { + private final MessageDigest prototype; + private final int bytes; + private final boolean supportsClone; + private final String toString; + + MessageDigestHashFunction(String algorithmName, String toString) { + this.prototype = MessageDigestHashFunction.getMessageDigest(algorithmName); + this.bytes = this.prototype.getDigestLength(); + this.toString = Preconditions.checkNotNull(toString); + this.supportsClone = this.supportsClone(); + } + + MessageDigestHashFunction(String algorithmName, int bytes, String toString) { + this.toString = Preconditions.checkNotNull(toString); + this.prototype = MessageDigestHashFunction.getMessageDigest(algorithmName); + int maxLength = this.prototype.getDigestLength(); + Preconditions.checkArgument(bytes >= 4 && bytes <= maxLength, "bytes (%s) must be >= 4 and < %s", bytes, maxLength); + this.bytes = bytes; + this.supportsClone = this.supportsClone(); + } + + private boolean supportsClone() { + try { + this.prototype.clone(); + return true; + } + catch (CloneNotSupportedException e) { + return false; + } + } + + @Override + public int bits() { + return this.bytes * 8; + } + + public String toString() { + return this.toString; + } + + private static MessageDigest getMessageDigest(String algorithmName) { + try { + return MessageDigest.getInstance(algorithmName); + } + catch (NoSuchAlgorithmException e) { + throw new AssertionError((Object)e); + } + } + + @Override + public Hasher newHasher() { + if (this.supportsClone) { + try { + return new MessageDigestHasher((MessageDigest)this.prototype.clone(), this.bytes); + } + catch (CloneNotSupportedException cloneNotSupportedException) { + // empty catch block + } + } + return new MessageDigestHasher(MessageDigestHashFunction.getMessageDigest(this.prototype.getAlgorithm()), this.bytes); + } + + Object writeReplace() { + return new SerializedForm(this.prototype.getAlgorithm(), this.bytes, this.toString); + } + + private static final class MessageDigestHasher + extends AbstractByteHasher { + private final MessageDigest digest; + private final int bytes; + private boolean done; + + private MessageDigestHasher(MessageDigest digest, int bytes) { + this.digest = digest; + this.bytes = bytes; + } + + @Override + protected void update(byte b) { + this.checkNotDone(); + this.digest.update(b); + } + + @Override + protected void update(byte[] b) { + this.checkNotDone(); + this.digest.update(b); + } + + @Override + protected void update(byte[] b, int off, int len) { + this.checkNotDone(); + this.digest.update(b, off, len); + } + + private void checkNotDone() { + Preconditions.checkState(!this.done, "Cannot re-use a Hasher after calling hash() on it"); + } + + @Override + public HashCode hash() { + this.checkNotDone(); + this.done = true; + return this.bytes == this.digest.getDigestLength() ? HashCode.fromBytesNoCopy(this.digest.digest()) : HashCode.fromBytesNoCopy(Arrays.copyOf(this.digest.digest(), this.bytes)); + } + } + + private static final class SerializedForm + implements Serializable { + private final String algorithmName; + private final int bytes; + private final String toString; + private static final long serialVersionUID = 0L; + + private SerializedForm(String algorithmName, int bytes, String toString) { + this.algorithmName = algorithmName; + this.bytes = bytes; + this.toString = toString; + } + + private Object readResolve() { + return new MessageDigestHashFunction(this.algorithmName, this.bytes, this.toString); + } + } +} diff --git a/src/com/google/common/hash/Murmur3_128HashFunction.java b/src/com/google/common/hash/Murmur3_128HashFunction.java new file mode 100644 index 0000000..97a7cb6 --- /dev/null +++ b/src/com/google/common/hash/Murmur3_128HashFunction.java @@ -0,0 +1,182 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.primitives.UnsignedBytes; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import javax.annotation.Nullable; + +final class Murmur3_128HashFunction +extends AbstractStreamingHashFunction +implements Serializable { + private final int seed; + private static final long serialVersionUID = 0L; + + Murmur3_128HashFunction(int seed) { + this.seed = seed; + } + + @Override + public int bits() { + return 128; + } + + @Override + public Hasher newHasher() { + return new Murmur3_128Hasher(this.seed); + } + + public String toString() { + int n = this.seed; + return new StringBuilder(32).append("Hashing.murmur3_128(").append(n).append(")").toString(); + } + + public boolean equals(@Nullable Object object) { + if (object instanceof Murmur3_128HashFunction) { + Murmur3_128HashFunction other = (Murmur3_128HashFunction)object; + return this.seed == other.seed; + } + return false; + } + + public int hashCode() { + return this.getClass().hashCode() ^ this.seed; + } + + private static final class Murmur3_128Hasher + extends AbstractStreamingHashFunction.AbstractStreamingHasher { + private static final int CHUNK_SIZE = 16; + private static final long C1 = -8663945395140668459L; + private static final long C2 = 5545529020109919103L; + private long h1; + private long h2; + private int length; + + Murmur3_128Hasher(int seed) { + super(16); + this.h1 = seed; + this.h2 = seed; + this.length = 0; + } + + @Override + protected void process(ByteBuffer bb) { + long k1 = bb.getLong(); + long k2 = bb.getLong(); + this.bmix64(k1, k2); + this.length += 16; + } + + private void bmix64(long k1, long k2) { + this.h1 ^= Murmur3_128Hasher.mixK1(k1); + this.h1 = Long.rotateLeft(this.h1, 27); + this.h1 += this.h2; + this.h1 = this.h1 * 5L + 1390208809L; + this.h2 ^= Murmur3_128Hasher.mixK2(k2); + this.h2 = Long.rotateLeft(this.h2, 31); + this.h2 += this.h1; + this.h2 = this.h2 * 5L + 944331445L; + } + + @Override + protected void processRemaining(ByteBuffer bb) { + long k1 = 0L; + long k2 = 0L; + this.length += bb.remaining(); + switch (bb.remaining()) { + case 15: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(14)) << 48; + } + case 14: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(13)) << 40; + } + case 13: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(12)) << 32; + } + case 12: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(11)) << 24; + } + case 11: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(10)) << 16; + } + case 10: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(9)) << 8; + } + case 9: { + k2 ^= (long)UnsignedBytes.toInt(bb.get(8)); + } + case 8: { + k1 ^= bb.getLong(); + break; + } + case 7: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(6)) << 48; + } + case 6: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(5)) << 40; + } + case 5: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(4)) << 32; + } + case 4: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(3)) << 24; + } + case 3: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(2)) << 16; + } + case 2: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(1)) << 8; + } + case 1: { + k1 ^= (long)UnsignedBytes.toInt(bb.get(0)); + break; + } + default: { + throw new AssertionError((Object)"Should never get here."); + } + } + this.h1 ^= Murmur3_128Hasher.mixK1(k1); + this.h2 ^= Murmur3_128Hasher.mixK2(k2); + } + + @Override + public HashCode makeHash() { + this.h1 ^= (long)this.length; + this.h2 ^= (long)this.length; + this.h1 += this.h2; + this.h2 += this.h1; + this.h1 = Murmur3_128Hasher.fmix64(this.h1); + this.h2 = Murmur3_128Hasher.fmix64(this.h2); + this.h1 += this.h2; + this.h2 += this.h1; + return HashCode.fromBytesNoCopy(ByteBuffer.wrap(new byte[16]).order(ByteOrder.LITTLE_ENDIAN).putLong(this.h1).putLong(this.h2).array()); + } + + private static long fmix64(long k) { + k ^= k >>> 33; + k *= -49064778989728563L; + k ^= k >>> 33; + k *= -4265267296055464877L; + k ^= k >>> 33; + return k; + } + + private static long mixK1(long k1) { + k1 *= -8663945395140668459L; + k1 = Long.rotateLeft(k1, 31); + return k1 *= 5545529020109919103L; + } + + private static long mixK2(long k2) { + k2 *= 5545529020109919103L; + k2 = Long.rotateLeft(k2, 33); + return k2 *= -8663945395140668459L; + } + } +} diff --git a/src/com/google/common/hash/Murmur3_32HashFunction.java b/src/com/google/common/hash/Murmur3_32HashFunction.java new file mode 100644 index 0000000..2e5f287 --- /dev/null +++ b/src/com/google/common/hash/Murmur3_32HashFunction.java @@ -0,0 +1,146 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import com.google.common.primitives.UnsignedBytes; +import java.io.Serializable; +import java.nio.ByteBuffer; +import javax.annotation.Nullable; + +final class Murmur3_32HashFunction +extends AbstractStreamingHashFunction +implements Serializable { + private static final int C1 = -862048943; + private static final int C2 = 461845907; + private final int seed; + private static final long serialVersionUID = 0L; + + Murmur3_32HashFunction(int seed) { + this.seed = seed; + } + + @Override + public int bits() { + return 32; + } + + @Override + public Hasher newHasher() { + return new Murmur3_32Hasher(this.seed); + } + + public String toString() { + int n = this.seed; + return new StringBuilder(31).append("Hashing.murmur3_32(").append(n).append(")").toString(); + } + + public boolean equals(@Nullable Object object) { + if (object instanceof Murmur3_32HashFunction) { + Murmur3_32HashFunction other = (Murmur3_32HashFunction)object; + return this.seed == other.seed; + } + return false; + } + + public int hashCode() { + return this.getClass().hashCode() ^ this.seed; + } + + @Override + public HashCode hashInt(int input) { + int k1 = Murmur3_32HashFunction.mixK1(input); + int h1 = Murmur3_32HashFunction.mixH1(this.seed, k1); + return Murmur3_32HashFunction.fmix(h1, 4); + } + + @Override + public HashCode hashLong(long input) { + int low = (int)input; + int high = (int)(input >>> 32); + int k1 = Murmur3_32HashFunction.mixK1(low); + int h1 = Murmur3_32HashFunction.mixH1(this.seed, k1); + k1 = Murmur3_32HashFunction.mixK1(high); + h1 = Murmur3_32HashFunction.mixH1(h1, k1); + return Murmur3_32HashFunction.fmix(h1, 8); + } + + @Override + public HashCode hashUnencodedChars(CharSequence input) { + int h1 = this.seed; + for (int i = 1; i < input.length(); i += 2) { + int k1 = input.charAt(i - 1) | input.charAt(i) << 16; + k1 = Murmur3_32HashFunction.mixK1(k1); + h1 = Murmur3_32HashFunction.mixH1(h1, k1); + } + if ((input.length() & 1) == 1) { + int k1 = input.charAt(input.length() - 1); + k1 = Murmur3_32HashFunction.mixK1(k1); + h1 ^= k1; + } + return Murmur3_32HashFunction.fmix(h1, 2 * input.length()); + } + + private static int mixK1(int k1) { + k1 *= -862048943; + k1 = Integer.rotateLeft(k1, 15); + return k1 *= 461845907; + } + + private static int mixH1(int h1, int k1) { + h1 ^= k1; + h1 = Integer.rotateLeft(h1, 13); + h1 = h1 * 5 + -430675100; + return h1; + } + + private static HashCode fmix(int h1, int length) { + h1 ^= length; + h1 ^= h1 >>> 16; + h1 *= -2048144789; + h1 ^= h1 >>> 13; + h1 *= -1028477387; + h1 ^= h1 >>> 16; + return HashCode.fromInt(h1); + } + + private static final class Murmur3_32Hasher + extends AbstractStreamingHashFunction.AbstractStreamingHasher { + private static final int CHUNK_SIZE = 4; + private int h1; + private int length; + + Murmur3_32Hasher(int seed) { + super(4); + this.h1 = seed; + this.length = 0; + } + + @Override + protected void process(ByteBuffer bb) { + int k1 = Murmur3_32HashFunction.mixK1(bb.getInt()); + this.h1 = Murmur3_32HashFunction.mixH1(this.h1, k1); + this.length += 4; + } + + @Override + protected void processRemaining(ByteBuffer bb) { + this.length += bb.remaining(); + int k1 = 0; + int i = 0; + while (bb.hasRemaining()) { + k1 ^= UnsignedBytes.toInt(bb.get()) << i; + i += 8; + } + this.h1 ^= Murmur3_32HashFunction.mixK1(k1); + } + + @Override + public HashCode makeHash() { + return Murmur3_32HashFunction.fmix(this.h1, this.length); + } + } +} diff --git a/src/com/google/common/hash/PrimitiveSink.java b/src/com/google/common/hash/PrimitiveSink.java new file mode 100644 index 0000000..a96eace --- /dev/null +++ b/src/com/google/common/hash/PrimitiveSink.java @@ -0,0 +1,34 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import java.nio.charset.Charset; + +@Beta +public interface PrimitiveSink { + public PrimitiveSink putByte(byte var1); + + public PrimitiveSink putBytes(byte[] var1); + + public PrimitiveSink putBytes(byte[] var1, int var2, int var3); + + public PrimitiveSink putShort(short var1); + + public PrimitiveSink putInt(int var1); + + public PrimitiveSink putLong(long var1); + + public PrimitiveSink putFloat(float var1); + + public PrimitiveSink putDouble(double var1); + + public PrimitiveSink putBoolean(boolean var1); + + public PrimitiveSink putChar(char var1); + + public PrimitiveSink putUnencodedChars(CharSequence var1); + + public PrimitiveSink putString(CharSequence var1, Charset var2); +} diff --git a/src/com/google/common/hash/SipHashFunction.java b/src/com/google/common/hash/SipHashFunction.java new file mode 100644 index 0000000..57dba6f --- /dev/null +++ b/src/com/google/common/hash/SipHashFunction.java @@ -0,0 +1,134 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.hash.AbstractStreamingHashFunction; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hasher; +import java.io.Serializable; +import java.nio.ByteBuffer; +import javax.annotation.Nullable; + +final class SipHashFunction +extends AbstractStreamingHashFunction +implements Serializable { + private final int c; + private final int d; + private final long k0; + private final long k1; + private static final long serialVersionUID = 0L; + + SipHashFunction(int c, int d, long k0, long k1) { + Preconditions.checkArgument(c > 0, "The number of SipRound iterations (c=%s) during Compression must be positive.", c); + Preconditions.checkArgument(d > 0, "The number of SipRound iterations (d=%s) during Finalization must be positive.", d); + this.c = c; + this.d = d; + this.k0 = k0; + this.k1 = k1; + } + + @Override + public int bits() { + return 64; + } + + @Override + public Hasher newHasher() { + return new SipHasher(this.c, this.d, this.k0, this.k1); + } + + public String toString() { + int n = this.c; + int n2 = this.d; + long l = this.k0; + long l2 = this.k1; + return new StringBuilder(81).append("Hashing.sipHash").append(n).append(n2).append("(").append(l).append(", ").append(l2).append(")").toString(); + } + + public boolean equals(@Nullable Object object) { + if (object instanceof SipHashFunction) { + SipHashFunction other = (SipHashFunction)object; + return this.c == other.c && this.d == other.d && this.k0 == other.k0 && this.k1 == other.k1; + } + return false; + } + + public int hashCode() { + return (int)((long)(this.getClass().hashCode() ^ this.c ^ this.d) ^ this.k0 ^ this.k1); + } + + private static final class SipHasher + extends AbstractStreamingHashFunction.AbstractStreamingHasher { + private static final int CHUNK_SIZE = 8; + private final int c; + private final int d; + private long v0 = 8317987319222330741L; + private long v1 = 7237128888997146477L; + private long v2 = 7816392313619706465L; + private long v3 = 8387220255154660723L; + private long b = 0L; + private long finalM = 0L; + + SipHasher(int c, int d, long k0, long k1) { + super(8); + this.c = c; + this.d = d; + this.v0 ^= k0; + this.v1 ^= k1; + this.v2 ^= k0; + this.v3 ^= k1; + } + + @Override + protected void process(ByteBuffer buffer) { + this.b += 8L; + this.processM(buffer.getLong()); + } + + @Override + protected void processRemaining(ByteBuffer buffer) { + this.b += (long)buffer.remaining(); + int i = 0; + while (buffer.hasRemaining()) { + this.finalM ^= ((long)buffer.get() & 0xFFL) << i; + i += 8; + } + } + + @Override + public HashCode makeHash() { + this.finalM ^= this.b << 56; + this.processM(this.finalM); + this.v2 ^= 0xFFL; + this.sipRound(this.d); + return HashCode.fromLong(this.v0 ^ this.v1 ^ this.v2 ^ this.v3); + } + + private void processM(long m) { + this.v3 ^= m; + this.sipRound(this.c); + this.v0 ^= m; + } + + private void sipRound(int iterations) { + for (int i = 0; i < iterations; ++i) { + this.v0 += this.v1; + this.v2 += this.v3; + this.v1 = Long.rotateLeft(this.v1, 13); + this.v3 = Long.rotateLeft(this.v3, 16); + this.v1 ^= this.v0; + this.v3 ^= this.v2; + this.v0 = Long.rotateLeft(this.v0, 32); + this.v2 += this.v1; + this.v0 += this.v3; + this.v1 = Long.rotateLeft(this.v1, 17); + this.v3 = Long.rotateLeft(this.v3, 21); + this.v1 ^= this.v2; + this.v3 ^= this.v0; + this.v2 = Long.rotateLeft(this.v2, 32); + } + } + } +} diff --git a/src/com/google/common/hash/package-info.java b/src/com/google/common/hash/package-info.java new file mode 100644 index 0000000..17c9c18 --- /dev/null +++ b/src/com/google/common/hash/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.hash; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/html/HtmlEscapers.java b/src/com/google/common/html/HtmlEscapers.java new file mode 100644 index 0000000..cd42e68 --- /dev/null +++ b/src/com/google/common/html/HtmlEscapers.java @@ -0,0 +1,22 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.html; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; + +@Beta +@GwtCompatible +public final class HtmlEscapers { + private static final Escaper HTML_ESCAPER = Escapers.builder().addEscape('\"', """).addEscape('\'', "'").addEscape('&', "&").addEscape('<', "<").addEscape('>', ">").build(); + + public static Escaper htmlEscaper() { + return HTML_ESCAPER; + } + + private HtmlEscapers() { + } +} diff --git a/src/com/google/common/html/package-info.java b/src/com/google/common/html/package-info.java new file mode 100644 index 0000000..a719584 --- /dev/null +++ b/src/com/google/common/html/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.html; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/io/AppendableWriter.java b/src/com/google/common/io/AppendableWriter.java new file mode 100644 index 0000000..b3a8783 --- /dev/null +++ b/src/com/google/common/io/AppendableWriter.java @@ -0,0 +1,88 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.Writer; +import javax.annotation.Nullable; + +class AppendableWriter +extends Writer { + private final Appendable target; + private boolean closed; + + AppendableWriter(Appendable target) { + this.target = Preconditions.checkNotNull(target); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + this.checkNotClosed(); + this.target.append(new String(cbuf, off, len)); + } + + @Override + public void flush() throws IOException { + this.checkNotClosed(); + if (this.target instanceof Flushable) { + ((Flushable)((Object)this.target)).flush(); + } + } + + @Override + public void close() throws IOException { + this.closed = true; + if (this.target instanceof Closeable) { + ((Closeable)((Object)this.target)).close(); + } + } + + @Override + public void write(int c) throws IOException { + this.checkNotClosed(); + this.target.append((char)c); + } + + @Override + public void write(@Nullable String str) throws IOException { + this.checkNotClosed(); + this.target.append(str); + } + + @Override + public void write(@Nullable String str, int off, int len) throws IOException { + this.checkNotClosed(); + this.target.append(str, off, off + len); + } + + @Override + public Writer append(char c) throws IOException { + this.checkNotClosed(); + this.target.append(c); + return this; + } + + @Override + public Writer append(@Nullable CharSequence charSeq) throws IOException { + this.checkNotClosed(); + this.target.append(charSeq); + return this; + } + + @Override + public Writer append(@Nullable CharSequence charSeq, int start, int end) throws IOException { + this.checkNotClosed(); + this.target.append(charSeq, start, end); + return this; + } + + private void checkNotClosed() throws IOException { + if (this.closed) { + throw new IOException("Cannot write to a closed writer."); + } + } +} diff --git a/src/com/google/common/io/BaseEncoding.java b/src/com/google/common/io/BaseEncoding.java new file mode 100644 index 0000000..7b8ec1c --- /dev/null +++ b/src/com/google/common/io/BaseEncoding.java @@ -0,0 +1,610 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.io.ByteSink; +import com.google.common.io.ByteSource; +import com.google.common.io.CharSink; +import com.google.common.io.CharSource; +import com.google.common.io.GwtWorkarounds; +import com.google.common.math.IntMath; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.math.RoundingMode; +import java.util.Arrays; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible(emulated=true) +public abstract class BaseEncoding { + private static final BaseEncoding BASE64 = new StandardBaseEncoding("base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", Character.valueOf('=')); + private static final BaseEncoding BASE64_URL = new StandardBaseEncoding("base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", Character.valueOf('=')); + private static final BaseEncoding BASE32 = new StandardBaseEncoding("base32()", "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", Character.valueOf('=')); + private static final BaseEncoding BASE32_HEX = new StandardBaseEncoding("base32Hex()", "0123456789ABCDEFGHIJKLMNOPQRSTUV", Character.valueOf('=')); + private static final BaseEncoding BASE16 = new StandardBaseEncoding("base16()", "0123456789ABCDEF", null); + + BaseEncoding() { + } + + public String encode(byte[] bytes) { + return this.encode(Preconditions.checkNotNull(bytes), 0, bytes.length); + } + + public final String encode(byte[] bytes, int off, int len) { + Preconditions.checkNotNull(bytes); + Preconditions.checkPositionIndexes(off, off + len, bytes.length); + GwtWorkarounds.CharOutput result = GwtWorkarounds.stringBuilderOutput(this.maxEncodedSize(len)); + GwtWorkarounds.ByteOutput byteOutput = this.encodingStream(result); + try { + for (int i = 0; i < len; ++i) { + byteOutput.write(bytes[off + i]); + } + byteOutput.close(); + } + catch (IOException impossible) { + throw new AssertionError((Object)"impossible"); + } + return result.toString(); + } + + @GwtIncompatible(value="Writer,OutputStream") + public final OutputStream encodingStream(Writer writer) { + return GwtWorkarounds.asOutputStream(this.encodingStream(GwtWorkarounds.asCharOutput(writer))); + } + + @GwtIncompatible(value="ByteSink,CharSink") + public final ByteSink encodingSink(final CharSink encodedSink) { + Preconditions.checkNotNull(encodedSink); + return new ByteSink(){ + + @Override + public OutputStream openStream() throws IOException { + return BaseEncoding.this.encodingStream(encodedSink.openStream()); + } + }; + } + + private static byte[] extract(byte[] result, int length) { + if (length == result.length) { + return result; + } + byte[] trunc = new byte[length]; + System.arraycopy(result, 0, trunc, 0, length); + return trunc; + } + + public final byte[] decode(CharSequence chars) { + try { + return this.decodeChecked(chars); + } + catch (DecodingException badInput) { + throw new IllegalArgumentException(badInput); + } + } + + final byte[] decodeChecked(CharSequence chars) throws DecodingException { + chars = this.padding().trimTrailingFrom(chars); + GwtWorkarounds.ByteInput decodedInput = this.decodingStream(GwtWorkarounds.asCharInput(chars)); + byte[] tmp = new byte[this.maxDecodedSize(chars.length())]; + int index = 0; + try { + int i = decodedInput.read(); + while (i != -1) { + tmp[index++] = (byte)i; + i = decodedInput.read(); + } + } + catch (DecodingException badInput) { + throw badInput; + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + return BaseEncoding.extract(tmp, index); + } + + @GwtIncompatible(value="Reader,InputStream") + public final InputStream decodingStream(Reader reader) { + return GwtWorkarounds.asInputStream(this.decodingStream(GwtWorkarounds.asCharInput(reader))); + } + + @GwtIncompatible(value="ByteSource,CharSource") + public final ByteSource decodingSource(final CharSource encodedSource) { + Preconditions.checkNotNull(encodedSource); + return new ByteSource(){ + + @Override + public InputStream openStream() throws IOException { + return BaseEncoding.this.decodingStream(encodedSource.openStream()); + } + }; + } + + abstract int maxEncodedSize(int var1); + + abstract GwtWorkarounds.ByteOutput encodingStream(GwtWorkarounds.CharOutput var1); + + abstract int maxDecodedSize(int var1); + + abstract GwtWorkarounds.ByteInput decodingStream(GwtWorkarounds.CharInput var1); + + abstract CharMatcher padding(); + + @CheckReturnValue + public abstract BaseEncoding omitPadding(); + + @CheckReturnValue + public abstract BaseEncoding withPadChar(char var1); + + @CheckReturnValue + public abstract BaseEncoding withSeparator(String var1, int var2); + + @CheckReturnValue + public abstract BaseEncoding upperCase(); + + @CheckReturnValue + public abstract BaseEncoding lowerCase(); + + public static BaseEncoding base64() { + return BASE64; + } + + public static BaseEncoding base64Url() { + return BASE64_URL; + } + + public static BaseEncoding base32() { + return BASE32; + } + + public static BaseEncoding base32Hex() { + return BASE32_HEX; + } + + public static BaseEncoding base16() { + return BASE16; + } + + static GwtWorkarounds.CharInput ignoringInput(final GwtWorkarounds.CharInput delegate, final CharMatcher toIgnore) { + Preconditions.checkNotNull(delegate); + Preconditions.checkNotNull(toIgnore); + return new GwtWorkarounds.CharInput(){ + + @Override + public int read() throws IOException { + int readChar; + while ((readChar = delegate.read()) != -1 && toIgnore.matches((char)readChar)) { + } + return readChar; + } + + @Override + public void close() throws IOException { + delegate.close(); + } + }; + } + + static GwtWorkarounds.CharOutput separatingOutput(final GwtWorkarounds.CharOutput delegate, final String separator, final int afterEveryChars) { + Preconditions.checkNotNull(delegate); + Preconditions.checkNotNull(separator); + Preconditions.checkArgument(afterEveryChars > 0); + return new GwtWorkarounds.CharOutput(){ + int charsUntilSeparator; + { + this.charsUntilSeparator = afterEveryChars; + } + + @Override + public void write(char c) throws IOException { + if (this.charsUntilSeparator == 0) { + for (int i = 0; i < separator.length(); ++i) { + delegate.write(separator.charAt(i)); + } + this.charsUntilSeparator = afterEveryChars; + } + delegate.write(c); + --this.charsUntilSeparator; + } + + @Override + public void flush() throws IOException { + delegate.flush(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + }; + } + + static final class SeparatedBaseEncoding + extends BaseEncoding { + private final BaseEncoding delegate; + private final String separator; + private final int afterEveryChars; + private final CharMatcher separatorChars; + + SeparatedBaseEncoding(BaseEncoding delegate, String separator, int afterEveryChars) { + this.delegate = Preconditions.checkNotNull(delegate); + this.separator = Preconditions.checkNotNull(separator); + this.afterEveryChars = afterEveryChars; + Preconditions.checkArgument(afterEveryChars > 0, "Cannot add a separator after every %s chars", afterEveryChars); + this.separatorChars = CharMatcher.anyOf(separator).precomputed(); + } + + @Override + CharMatcher padding() { + return this.delegate.padding(); + } + + @Override + int maxEncodedSize(int bytes) { + int unseparatedSize = this.delegate.maxEncodedSize(bytes); + return unseparatedSize + this.separator.length() * IntMath.divide(Math.max(0, unseparatedSize - 1), this.afterEveryChars, RoundingMode.FLOOR); + } + + @Override + GwtWorkarounds.ByteOutput encodingStream(GwtWorkarounds.CharOutput output) { + return this.delegate.encodingStream(SeparatedBaseEncoding.separatingOutput(output, this.separator, this.afterEveryChars)); + } + + @Override + int maxDecodedSize(int chars) { + return this.delegate.maxDecodedSize(chars); + } + + @Override + GwtWorkarounds.ByteInput decodingStream(GwtWorkarounds.CharInput input) { + return this.delegate.decodingStream(SeparatedBaseEncoding.ignoringInput(input, this.separatorChars)); + } + + @Override + public BaseEncoding omitPadding() { + return this.delegate.omitPadding().withSeparator(this.separator, this.afterEveryChars); + } + + @Override + public BaseEncoding withPadChar(char padChar) { + return this.delegate.withPadChar(padChar).withSeparator(this.separator, this.afterEveryChars); + } + + @Override + public BaseEncoding withSeparator(String separator, int afterEveryChars) { + throw new UnsupportedOperationException("Already have a separator"); + } + + @Override + public BaseEncoding upperCase() { + return this.delegate.upperCase().withSeparator(this.separator, this.afterEveryChars); + } + + @Override + public BaseEncoding lowerCase() { + return this.delegate.lowerCase().withSeparator(this.separator, this.afterEveryChars); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.delegate.toString())); + String string2 = String.valueOf(String.valueOf(this.separator)); + int n = this.afterEveryChars; + return new StringBuilder(31 + string.length() + string2.length()).append(string).append(".withSeparator(\"").append(string2).append("\", ").append(n).append(")").toString(); + } + } + + static final class StandardBaseEncoding + extends BaseEncoding { + private final Alphabet alphabet; + @Nullable + private final Character paddingChar; + private transient BaseEncoding upperCase; + private transient BaseEncoding lowerCase; + + StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) { + this(new Alphabet(name, alphabetChars.toCharArray()), paddingChar); + } + + StandardBaseEncoding(Alphabet alphabet, @Nullable Character paddingChar) { + this.alphabet = Preconditions.checkNotNull(alphabet); + Preconditions.checkArgument(paddingChar == null || !alphabet.matches(paddingChar.charValue()), "Padding character %s was already in alphabet", paddingChar); + this.paddingChar = paddingChar; + } + + @Override + CharMatcher padding() { + return this.paddingChar == null ? CharMatcher.NONE : CharMatcher.is(this.paddingChar.charValue()); + } + + @Override + int maxEncodedSize(int bytes) { + return this.alphabet.charsPerChunk * IntMath.divide(bytes, this.alphabet.bytesPerChunk, RoundingMode.CEILING); + } + + @Override + GwtWorkarounds.ByteOutput encodingStream(final GwtWorkarounds.CharOutput out) { + Preconditions.checkNotNull(out); + return new GwtWorkarounds.ByteOutput(){ + int bitBuffer = 0; + int bitBufferLength = 0; + int writtenChars = 0; + + @Override + public void write(byte b) throws IOException { + this.bitBuffer <<= 8; + this.bitBuffer |= b & 0xFF; + this.bitBufferLength += 8; + while (this.bitBufferLength >= ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar) { + int charIndex = this.bitBuffer >> this.bitBufferLength - ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar & ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.mask; + out.write(StandardBaseEncoding.this.alphabet.encode(charIndex)); + ++this.writtenChars; + this.bitBufferLength -= ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar; + } + } + + @Override + public void flush() throws IOException { + out.flush(); + } + + @Override + public void close() throws IOException { + if (this.bitBufferLength > 0) { + int charIndex = this.bitBuffer << ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar - this.bitBufferLength & ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.mask; + out.write(StandardBaseEncoding.this.alphabet.encode(charIndex)); + ++this.writtenChars; + if (StandardBaseEncoding.this.paddingChar != null) { + while (this.writtenChars % ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.charsPerChunk != 0) { + out.write(StandardBaseEncoding.this.paddingChar.charValue()); + ++this.writtenChars; + } + } + } + out.close(); + } + }; + } + + @Override + int maxDecodedSize(int chars) { + return (int)(((long)this.alphabet.bitsPerChar * (long)chars + 7L) / 8L); + } + + @Override + GwtWorkarounds.ByteInput decodingStream(final GwtWorkarounds.CharInput reader) { + Preconditions.checkNotNull(reader); + return new GwtWorkarounds.ByteInput(){ + int bitBuffer = 0; + int bitBufferLength = 0; + int readChars = 0; + boolean hitPadding = false; + final CharMatcher paddingMatcher = StandardBaseEncoding.this.padding(); + + @Override + public int read() throws IOException { + while (true) { + int readChar; + if ((readChar = reader.read()) == -1) { + if (!this.hitPadding && !StandardBaseEncoding.this.alphabet.isValidPaddingStartPosition(this.readChars)) { + int n = this.readChars; + throw new DecodingException(new StringBuilder(32).append("Invalid input length ").append(n).toString()); + } + return -1; + } + ++this.readChars; + char ch = (char)readChar; + if (this.paddingMatcher.matches(ch)) { + if (!(this.hitPadding || this.readChars != 1 && StandardBaseEncoding.this.alphabet.isValidPaddingStartPosition(this.readChars - 1))) { + int n = this.readChars; + throw new DecodingException(new StringBuilder(41).append("Padding cannot start at index ").append(n).toString()); + } + this.hitPadding = true; + continue; + } + if (this.hitPadding) { + char c = ch; + int n = this.readChars; + throw new DecodingException(new StringBuilder(61).append("Expected padding character but found '").append(c).append("' at index ").append(n).toString()); + } + this.bitBuffer <<= ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar; + this.bitBuffer |= StandardBaseEncoding.this.alphabet.decode(ch); + this.bitBufferLength += ((StandardBaseEncoding)StandardBaseEncoding.this).alphabet.bitsPerChar; + if (this.bitBufferLength >= 8) break; + } + this.bitBufferLength -= 8; + return this.bitBuffer >> this.bitBufferLength & 0xFF; + } + + @Override + public void close() throws IOException { + reader.close(); + } + }; + } + + @Override + public BaseEncoding omitPadding() { + return this.paddingChar == null ? this : new StandardBaseEncoding(this.alphabet, null); + } + + @Override + public BaseEncoding withPadChar(char padChar) { + if (8 % this.alphabet.bitsPerChar == 0 || this.paddingChar != null && this.paddingChar.charValue() == padChar) { + return this; + } + return new StandardBaseEncoding(this.alphabet, Character.valueOf(padChar)); + } + + @Override + public BaseEncoding withSeparator(String separator, int afterEveryChars) { + Preconditions.checkNotNull(separator); + Preconditions.checkArgument(this.padding().or(this.alphabet).matchesNoneOf(separator), "Separator cannot contain alphabet or padding characters"); + return new SeparatedBaseEncoding(this, separator, afterEveryChars); + } + + @Override + public BaseEncoding upperCase() { + BaseEncoding result = this.upperCase; + if (result == null) { + Alphabet upper = this.alphabet.upperCase(); + this.upperCase = upper == this.alphabet ? this : new StandardBaseEncoding(upper, this.paddingChar); + result = this.upperCase; + } + return result; + } + + @Override + public BaseEncoding lowerCase() { + BaseEncoding result = this.lowerCase; + if (result == null) { + Alphabet lower = this.alphabet.lowerCase(); + this.lowerCase = lower == this.alphabet ? this : new StandardBaseEncoding(lower, this.paddingChar); + result = this.lowerCase; + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder("BaseEncoding."); + builder.append(this.alphabet.toString()); + if (8 % this.alphabet.bitsPerChar != 0) { + if (this.paddingChar == null) { + builder.append(".omitPadding()"); + } else { + builder.append(".withPadChar(").append(this.paddingChar).append(')'); + } + } + return builder.toString(); + } + } + + private static final class Alphabet + extends CharMatcher { + private final String name; + private final char[] chars; + final int mask; + final int bitsPerChar; + final int charsPerChunk; + final int bytesPerChunk; + private final byte[] decodabet; + private final boolean[] validPadding; + + Alphabet(String name, char[] chars) { + this.name = Preconditions.checkNotNull(name); + this.chars = Preconditions.checkNotNull(chars); + try { + this.bitsPerChar = IntMath.log2(chars.length, RoundingMode.UNNECESSARY); + } + catch (ArithmeticException e) { + int n = chars.length; + throw new IllegalArgumentException(new StringBuilder(35).append("Illegal alphabet length ").append(n).toString(), e); + } + int gcd = Math.min(8, Integer.lowestOneBit(this.bitsPerChar)); + this.charsPerChunk = 8 / gcd; + this.bytesPerChunk = this.bitsPerChar / gcd; + this.mask = chars.length - 1; + byte[] decodabet = new byte[128]; + Arrays.fill(decodabet, (byte)-1); + for (int i = 0; i < chars.length; ++i) { + char c = chars[i]; + Preconditions.checkArgument(CharMatcher.ASCII.matches(c), "Non-ASCII character: %s", Character.valueOf(c)); + Preconditions.checkArgument(decodabet[c] == -1, "Duplicate character: %s", Character.valueOf(c)); + decodabet[c] = (byte)i; + } + this.decodabet = decodabet; + boolean[] validPadding = new boolean[this.charsPerChunk]; + for (int i = 0; i < this.bytesPerChunk; ++i) { + validPadding[IntMath.divide((int)(i * 8), (int)this.bitsPerChar, (RoundingMode)RoundingMode.CEILING)] = true; + } + this.validPadding = validPadding; + } + + char encode(int bits) { + return this.chars[bits]; + } + + boolean isValidPaddingStartPosition(int index) { + return this.validPadding[index % this.charsPerChunk]; + } + + int decode(char ch) throws IOException { + if (ch > '\u007f' || this.decodabet[ch] == -1) { + char c = ch; + throw new DecodingException(new StringBuilder(25).append("Unrecognized character: ").append(c).toString()); + } + return this.decodabet[ch]; + } + + private boolean hasLowerCase() { + for (char c : this.chars) { + if (!Ascii.isLowerCase(c)) continue; + return true; + } + return false; + } + + private boolean hasUpperCase() { + for (char c : this.chars) { + if (!Ascii.isUpperCase(c)) continue; + return true; + } + return false; + } + + Alphabet upperCase() { + if (!this.hasLowerCase()) { + return this; + } + Preconditions.checkState(!this.hasUpperCase(), "Cannot call upperCase() on a mixed-case alphabet"); + char[] upperCased = new char[this.chars.length]; + for (int i = 0; i < this.chars.length; ++i) { + upperCased[i] = Ascii.toUpperCase(this.chars[i]); + } + return new Alphabet(String.valueOf(this.name).concat(".upperCase()"), upperCased); + } + + Alphabet lowerCase() { + if (!this.hasUpperCase()) { + return this; + } + Preconditions.checkState(!this.hasLowerCase(), "Cannot call lowerCase() on a mixed-case alphabet"); + char[] lowerCased = new char[this.chars.length]; + for (int i = 0; i < this.chars.length; ++i) { + lowerCased[i] = Ascii.toLowerCase(this.chars[i]); + } + return new Alphabet(String.valueOf(this.name).concat(".lowerCase()"), lowerCased); + } + + @Override + public boolean matches(char c) { + return CharMatcher.ASCII.matches(c) && this.decodabet[c] != -1; + } + + @Override + public String toString() { + return this.name; + } + } + + public static final class DecodingException + extends IOException { + DecodingException(String message) { + super(message); + } + + DecodingException(Throwable cause) { + super(cause); + } + } +} diff --git a/src/com/google/common/io/ByteArrayDataInput.java b/src/com/google/common/io/ByteArrayDataInput.java new file mode 100644 index 0000000..3ffcd63 --- /dev/null +++ b/src/com/google/common/io/ByteArrayDataInput.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import java.io.DataInput; + +public interface ByteArrayDataInput +extends DataInput { + @Override + public void readFully(byte[] var1); + + @Override + public void readFully(byte[] var1, int var2, int var3); + + @Override + public int skipBytes(int var1); + + @Override + public boolean readBoolean(); + + @Override + public byte readByte(); + + @Override + public int readUnsignedByte(); + + @Override + public short readShort(); + + @Override + public int readUnsignedShort(); + + @Override + public char readChar(); + + @Override + public int readInt(); + + @Override + public long readLong(); + + @Override + public float readFloat(); + + @Override + public double readDouble(); + + @Override + public String readLine(); + + @Override + public String readUTF(); +} diff --git a/src/com/google/common/io/ByteArrayDataOutput.java b/src/com/google/common/io/ByteArrayDataOutput.java new file mode 100644 index 0000000..08f2684 --- /dev/null +++ b/src/com/google/common/io/ByteArrayDataOutput.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import java.io.DataOutput; + +public interface ByteArrayDataOutput +extends DataOutput { + @Override + public void write(int var1); + + @Override + public void write(byte[] var1); + + @Override + public void write(byte[] var1, int var2, int var3); + + @Override + public void writeBoolean(boolean var1); + + @Override + public void writeByte(int var1); + + @Override + public void writeShort(int var1); + + @Override + public void writeChar(int var1); + + @Override + public void writeInt(int var1); + + @Override + public void writeLong(long var1); + + @Override + public void writeFloat(float var1); + + @Override + public void writeDouble(double var1); + + @Override + public void writeChars(String var1); + + @Override + public void writeUTF(String var1); + + @Override + @Deprecated + public void writeBytes(String var1); + + public byte[] toByteArray(); +} diff --git a/src/com/google/common/io/ByteProcessor.java b/src/com/google/common/io/ByteProcessor.java new file mode 100644 index 0000000..66b9a12 --- /dev/null +++ b/src/com/google/common/io/ByteProcessor.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.IOException; + +@Beta +public interface ByteProcessor { + public boolean processBytes(byte[] var1, int var2, int var3) throws IOException; + + public T getResult(); +} diff --git a/src/com/google/common/io/ByteSink.java b/src/com/google/common/io/ByteSink.java new file mode 100644 index 0000000..69a3b0b --- /dev/null +++ b/src/com/google/common/io/ByteSink.java @@ -0,0 +1,86 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import com.google.common.io.ByteStreams; +import com.google.common.io.CharSink; +import com.google.common.io.Closer; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.Charset; + +public abstract class ByteSink { + protected ByteSink() { + } + + public CharSink asCharSink(Charset charset) { + return new AsCharSink(charset); + } + + public abstract OutputStream openStream() throws IOException; + + public OutputStream openBufferedStream() throws IOException { + OutputStream out = this.openStream(); + return out instanceof BufferedOutputStream ? (BufferedOutputStream)out : new BufferedOutputStream(out); + } + + public void write(byte[] bytes) throws IOException { + Preconditions.checkNotNull(bytes); + Closer closer = Closer.create(); + try { + OutputStream out = closer.register(this.openStream()); + out.write(bytes); + out.flush(); + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public long writeFrom(InputStream input) throws IOException { + Preconditions.checkNotNull(input); + Closer closer = Closer.create(); + try { + OutputStream out = closer.register(this.openStream()); + long written = ByteStreams.copy(input, out); + out.flush(); + long l = written; + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + private final class AsCharSink + extends CharSink { + private final Charset charset; + + private AsCharSink(Charset charset) { + this.charset = Preconditions.checkNotNull(charset); + } + + @Override + public Writer openStream() throws IOException { + return new OutputStreamWriter(ByteSink.this.openStream(), this.charset); + } + + public String toString() { + String string = String.valueOf(String.valueOf(ByteSink.this.toString())); + String string2 = String.valueOf(String.valueOf(this.charset)); + return new StringBuilder(13 + string.length() + string2.length()).append(string).append(".asCharSink(").append(string2).append(")").toString(); + } + } +} diff --git a/src/com/google/common/io/ByteSource.java b/src/com/google/common/io/ByteSource.java new file mode 100644 index 0000000..50e7049 --- /dev/null +++ b/src/com/google/common/io/ByteSource.java @@ -0,0 +1,452 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Ascii; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.hash.Funnels; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import com.google.common.io.BaseEncoding; +import com.google.common.io.ByteProcessor; +import com.google.common.io.ByteSink; +import com.google.common.io.ByteStreams; +import com.google.common.io.CharSource; +import com.google.common.io.Closer; +import com.google.common.io.MultiInputStream; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Iterator; + +public abstract class ByteSource { + private static final int BUF_SIZE = 4096; + private static final byte[] countBuffer = new byte[4096]; + + protected ByteSource() { + } + + public CharSource asCharSource(Charset charset) { + return new AsCharSource(charset); + } + + public abstract InputStream openStream() throws IOException; + + public InputStream openBufferedStream() throws IOException { + InputStream in = this.openStream(); + return in instanceof BufferedInputStream ? (BufferedInputStream)in : new BufferedInputStream(in); + } + + public ByteSource slice(long offset, long length) { + return new SlicedByteSource(offset, length); + } + + public boolean isEmpty() throws IOException { + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + boolean bl = in.read() == -1; + return bl; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public long size() throws IOException { + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + long l = this.countBySkipping(in); + return l; + } + catch (IOException e) { + } + finally { + closer.close(); + } + closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + long l = this.countByReading(in); + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + private long countBySkipping(InputStream in) throws IOException { + long count = 0L; + while (true) { + long skipped; + if ((skipped = in.skip(Math.min(in.available(), Integer.MAX_VALUE))) <= 0L) { + if (in.read() == -1) { + return count; + } + if (count == 0L && in.available() == 0) { + throw new IOException(); + } + ++count; + continue; + } + count += skipped; + } + } + + private long countByReading(InputStream in) throws IOException { + long read; + long count = 0L; + while ((read = (long)in.read(countBuffer)) != -1L) { + count += read; + } + return count; + } + + public long copyTo(OutputStream output) throws IOException { + Preconditions.checkNotNull(output); + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + long l = ByteStreams.copy(in, output); + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public long copyTo(ByteSink sink) throws IOException { + Preconditions.checkNotNull(sink); + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + OutputStream out = closer.register(sink.openStream()); + long l = ByteStreams.copy(in, out); + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public byte[] read() throws IOException { + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + byte[] byArray = ByteStreams.toByteArray(in); + return byArray; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + @Beta + public T read(ByteProcessor processor) throws IOException { + Preconditions.checkNotNull(processor); + Closer closer = Closer.create(); + try { + InputStream in = closer.register(this.openStream()); + T t = ByteStreams.readBytes(in, processor); + return t; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public HashCode hash(HashFunction hashFunction) throws IOException { + Hasher hasher = hashFunction.newHasher(); + this.copyTo(Funnels.asOutputStream(hasher)); + return hasher.hash(); + } + + /* + * Enabled aggressive block sorting + * Enabled unnecessary exception pruning + * Enabled aggressive exception aggregation + */ + public boolean contentEquals(ByteSource other) throws IOException { + Preconditions.checkNotNull(other); + byte[] buf1 = new byte[4096]; + byte[] buf2 = new byte[4096]; + Closer closer = Closer.create(); + try { + InputStream in1 = closer.register(this.openStream()); + InputStream in2 = closer.register(other.openStream()); + while (true) { + int read2; + int read1; + if ((read1 = ByteStreams.read(in1, buf1, 0, 4096)) != (read2 = ByteStreams.read(in2, buf2, 0, 4096)) || !Arrays.equals(buf1, buf2)) { + boolean bl = false; + return bl; + } + if (read1 != 4096) { + boolean bl = true; + return bl; + } + continue; + break; + } + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public static ByteSource concat(Iterable sources) { + return new ConcatenatedByteSource(sources); + } + + public static ByteSource concat(Iterator sources) { + return ByteSource.concat(ImmutableList.copyOf(sources)); + } + + public static ByteSource concat(ByteSource ... sources) { + return ByteSource.concat(ImmutableList.copyOf(sources)); + } + + public static ByteSource wrap(byte[] b) { + return new ByteArrayByteSource(b); + } + + public static ByteSource empty() { + return EmptyByteSource.INSTANCE; + } + + private static final class ConcatenatedByteSource + extends ByteSource { + private final Iterable sources; + + ConcatenatedByteSource(Iterable sources) { + this.sources = Preconditions.checkNotNull(sources); + } + + @Override + public InputStream openStream() throws IOException { + return new MultiInputStream(this.sources.iterator()); + } + + @Override + public boolean isEmpty() throws IOException { + for (ByteSource byteSource : this.sources) { + if (byteSource.isEmpty()) continue; + return false; + } + return true; + } + + @Override + public long size() throws IOException { + long result = 0L; + for (ByteSource byteSource : this.sources) { + result += byteSource.size(); + } + return result; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.sources)); + return new StringBuilder(19 + string.length()).append("ByteSource.concat(").append(string).append(")").toString(); + } + } + + private static final class EmptyByteSource + extends ByteArrayByteSource { + private static final EmptyByteSource INSTANCE = new EmptyByteSource(); + + private EmptyByteSource() { + super(new byte[0]); + } + + @Override + public CharSource asCharSource(Charset charset) { + Preconditions.checkNotNull(charset); + return CharSource.empty(); + } + + @Override + public byte[] read() { + return this.bytes; + } + + @Override + public String toString() { + return "ByteSource.empty()"; + } + } + + private static class ByteArrayByteSource + extends ByteSource { + protected final byte[] bytes; + + protected ByteArrayByteSource(byte[] bytes) { + this.bytes = Preconditions.checkNotNull(bytes); + } + + @Override + public InputStream openStream() { + return new ByteArrayInputStream(this.bytes); + } + + @Override + public InputStream openBufferedStream() throws IOException { + return this.openStream(); + } + + @Override + public boolean isEmpty() { + return this.bytes.length == 0; + } + + @Override + public long size() { + return this.bytes.length; + } + + @Override + public byte[] read() { + return (byte[])this.bytes.clone(); + } + + @Override + public long copyTo(OutputStream output) throws IOException { + output.write(this.bytes); + return this.bytes.length; + } + + @Override + public T read(ByteProcessor processor) throws IOException { + processor.processBytes(this.bytes, 0, this.bytes.length); + return processor.getResult(); + } + + @Override + public HashCode hash(HashFunction hashFunction) throws IOException { + return hashFunction.hashBytes(this.bytes); + } + + public String toString() { + String string = String.valueOf(String.valueOf(Ascii.truncate(BaseEncoding.base16().encode(this.bytes), 30, "..."))); + return new StringBuilder(17 + string.length()).append("ByteSource.wrap(").append(string).append(")").toString(); + } + } + + private final class SlicedByteSource + extends ByteSource { + private final long offset; + private final long length; + + private SlicedByteSource(long offset, long length) { + Preconditions.checkArgument(offset >= 0L, "offset (%s) may not be negative", offset); + Preconditions.checkArgument(length >= 0L, "length (%s) may not be negative", length); + this.offset = offset; + this.length = length; + } + + @Override + public InputStream openStream() throws IOException { + return this.sliceStream(ByteSource.this.openStream()); + } + + @Override + public InputStream openBufferedStream() throws IOException { + return this.sliceStream(ByteSource.this.openBufferedStream()); + } + + private InputStream sliceStream(InputStream in) throws IOException { + if (this.offset > 0L) { + try { + ByteStreams.skipFully(in, this.offset); + } + catch (Throwable e) { + Closer closer = Closer.create(); + closer.register(in); + try { + throw closer.rethrow(e); + } + catch (Throwable throwable) { + closer.close(); + throw throwable; + } + } + } + return ByteStreams.limit(in, this.length); + } + + @Override + public ByteSource slice(long offset, long length) { + Preconditions.checkArgument(offset >= 0L, "offset (%s) may not be negative", offset); + Preconditions.checkArgument(length >= 0L, "length (%s) may not be negative", length); + long maxLength = this.length - offset; + return ByteSource.this.slice(this.offset + offset, Math.min(length, maxLength)); + } + + @Override + public boolean isEmpty() throws IOException { + return this.length == 0L || super.isEmpty(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(ByteSource.this.toString())); + long l = this.offset; + long l2 = this.length; + return new StringBuilder(50 + string.length()).append(string).append(".slice(").append(l).append(", ").append(l2).append(")").toString(); + } + } + + private final class AsCharSource + extends CharSource { + private final Charset charset; + + private AsCharSource(Charset charset) { + this.charset = Preconditions.checkNotNull(charset); + } + + @Override + public Reader openStream() throws IOException { + return new InputStreamReader(ByteSource.this.openStream(), this.charset); + } + + public String toString() { + String string = String.valueOf(String.valueOf(ByteSource.this.toString())); + String string2 = String.valueOf(String.valueOf(this.charset)); + return new StringBuilder(15 + string.length() + string2.length()).append(string).append(".asCharSource(").append(string2).append(")").toString(); + } + } +} diff --git a/src/com/google/common/io/ByteStreams.java b/src/com/google/common/io/ByteStreams.java new file mode 100644 index 0000000..48624bc --- /dev/null +++ b/src/com/google/common/io/ByteStreams.java @@ -0,0 +1,593 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteProcessor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.Arrays; + +@Beta +public final class ByteStreams { + private static final int BUF_SIZE = 4096; + private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream(){ + + @Override + public void write(int b) { + } + + @Override + public void write(byte[] b) { + Preconditions.checkNotNull(b); + } + + @Override + public void write(byte[] b, int off, int len) { + Preconditions.checkNotNull(b); + } + + public String toString() { + return "ByteStreams.nullOutputStream()"; + } + }; + + private ByteStreams() { + } + + public static long copy(InputStream from, OutputStream to) throws IOException { + int r; + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + byte[] buf = new byte[4096]; + long total = 0L; + while ((r = from.read(buf)) != -1) { + to.write(buf, 0, r); + total += (long)r; + } + return total; + } + + public static long copy(ReadableByteChannel from, WritableByteChannel to) throws IOException { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + ByteBuffer buf = ByteBuffer.allocate(4096); + long total = 0L; + while (from.read(buf) != -1) { + buf.flip(); + while (buf.hasRemaining()) { + total += (long)to.write(buf); + } + buf.clear(); + } + return total; + } + + public static byte[] toByteArray(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteStreams.copy(in, out); + return out.toByteArray(); + } + + static byte[] toByteArray(InputStream in, int expectedSize) throws IOException { + int read; + byte[] bytes = new byte[expectedSize]; + for (int remaining = expectedSize; remaining > 0; remaining -= read) { + int off = expectedSize - remaining; + read = in.read(bytes, off, remaining); + if (read != -1) continue; + return Arrays.copyOf(bytes, off); + } + int b = in.read(); + if (b == -1) { + return bytes; + } + FastByteArrayOutputStream out = new FastByteArrayOutputStream(); + out.write(b); + ByteStreams.copy(in, out); + byte[] result = new byte[bytes.length + out.size()]; + System.arraycopy(bytes, 0, result, 0, bytes.length); + out.writeTo(result, bytes.length); + return result; + } + + public static ByteArrayDataInput newDataInput(byte[] bytes) { + return ByteStreams.newDataInput(new ByteArrayInputStream(bytes)); + } + + public static ByteArrayDataInput newDataInput(byte[] bytes, int start) { + Preconditions.checkPositionIndex(start, bytes.length); + return ByteStreams.newDataInput(new ByteArrayInputStream(bytes, start, bytes.length - start)); + } + + public static ByteArrayDataInput newDataInput(ByteArrayInputStream byteArrayInputStream) { + return new ByteArrayDataInputStream(Preconditions.checkNotNull(byteArrayInputStream)); + } + + public static ByteArrayDataOutput newDataOutput() { + return ByteStreams.newDataOutput(new ByteArrayOutputStream()); + } + + public static ByteArrayDataOutput newDataOutput(int size) { + Preconditions.checkArgument(size >= 0, "Invalid size: %s", size); + return ByteStreams.newDataOutput(new ByteArrayOutputStream(size)); + } + + public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputSteam) { + return new ByteArrayDataOutputStream(Preconditions.checkNotNull(byteArrayOutputSteam)); + } + + public static OutputStream nullOutputStream() { + return NULL_OUTPUT_STREAM; + } + + public static InputStream limit(InputStream in, long limit) { + return new LimitedInputStream(in, limit); + } + + public static void readFully(InputStream in, byte[] b) throws IOException { + ByteStreams.readFully(in, b, 0, b.length); + } + + public static void readFully(InputStream in, byte[] b, int off, int len) throws IOException { + int read = ByteStreams.read(in, b, off, len); + if (read != len) { + int n = read; + int n2 = len; + throw new EOFException(new StringBuilder(81).append("reached end of stream after reading ").append(n).append(" bytes; ").append(n2).append(" bytes expected").toString()); + } + } + + public static void skipFully(InputStream in, long n) throws IOException { + long toSkip = n; + while (n > 0L) { + long amt = in.skip(n); + if (amt == 0L) { + if (in.read() == -1) { + long skipped; + long l = skipped = toSkip - n; + long l2 = toSkip; + throw new EOFException(new StringBuilder(100).append("reached end of stream after skipping ").append(l).append(" bytes; ").append(l2).append(" bytes expected").toString()); + } + --n; + continue; + } + n -= amt; + } + } + + public static T readBytes(InputStream input, ByteProcessor processor) throws IOException { + int read; + Preconditions.checkNotNull(input); + Preconditions.checkNotNull(processor); + byte[] buf = new byte[4096]; + while ((read = input.read(buf)) != -1 && processor.processBytes(buf, 0, read)) { + } + return processor.getResult(); + } + + public static int read(InputStream in, byte[] b, int off, int len) throws IOException { + int total; + int result; + Preconditions.checkNotNull(in); + Preconditions.checkNotNull(b); + if (len < 0) { + throw new IndexOutOfBoundsException("len is negative"); + } + for (total = 0; total < len && (result = in.read(b, off + total, len - total)) != -1; total += result) { + } + return total; + } + + private static final class LimitedInputStream + extends FilterInputStream { + private long left; + private long mark = -1L; + + LimitedInputStream(InputStream in, long limit) { + super(in); + Preconditions.checkNotNull(in); + Preconditions.checkArgument(limit >= 0L, "limit must be non-negative"); + this.left = limit; + } + + @Override + public int available() throws IOException { + return (int)Math.min((long)this.in.available(), this.left); + } + + @Override + public synchronized void mark(int readLimit) { + this.in.mark(readLimit); + this.mark = this.left; + } + + @Override + public int read() throws IOException { + if (this.left == 0L) { + return -1; + } + int result = this.in.read(); + if (result != -1) { + --this.left; + } + return result; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (this.left == 0L) { + return -1; + } + int result = this.in.read(b, off, len = (int)Math.min((long)len, this.left)); + if (result != -1) { + this.left -= (long)result; + } + return result; + } + + @Override + public synchronized void reset() throws IOException { + if (!this.in.markSupported()) { + throw new IOException("Mark not supported"); + } + if (this.mark == -1L) { + throw new IOException("Mark not set"); + } + this.in.reset(); + this.left = this.mark; + } + + @Override + public long skip(long n) throws IOException { + n = Math.min(n, this.left); + long skipped = this.in.skip(n); + this.left -= skipped; + return skipped; + } + } + + private static class ByteArrayDataOutputStream + implements ByteArrayDataOutput { + final DataOutput output; + final ByteArrayOutputStream byteArrayOutputSteam; + + ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) { + this.byteArrayOutputSteam = byteArrayOutputSteam; + this.output = new DataOutputStream(byteArrayOutputSteam); + } + + @Override + public void write(int b) { + try { + this.output.write(b); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void write(byte[] b) { + try { + this.output.write(b); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void write(byte[] b, int off, int len) { + try { + this.output.write(b, off, len); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeBoolean(boolean v) { + try { + this.output.writeBoolean(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeByte(int v) { + try { + this.output.writeByte(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeBytes(String s) { + try { + this.output.writeBytes(s); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeChar(int v) { + try { + this.output.writeChar(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeChars(String s) { + try { + this.output.writeChars(s); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeDouble(double v) { + try { + this.output.writeDouble(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeFloat(float v) { + try { + this.output.writeFloat(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeInt(int v) { + try { + this.output.writeInt(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeLong(long v) { + try { + this.output.writeLong(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeShort(int v) { + try { + this.output.writeShort(v); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public void writeUTF(String s) { + try { + this.output.writeUTF(s); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public byte[] toByteArray() { + return this.byteArrayOutputSteam.toByteArray(); + } + } + + private static class ByteArrayDataInputStream + implements ByteArrayDataInput { + final DataInput input; + + ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) { + this.input = new DataInputStream(byteArrayInputStream); + } + + @Override + public void readFully(byte[] b) { + try { + this.input.readFully(b); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public void readFully(byte[] b, int off, int len) { + try { + this.input.readFully(b, off, len); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public int skipBytes(int n) { + try { + return this.input.skipBytes(n); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public boolean readBoolean() { + try { + return this.input.readBoolean(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public byte readByte() { + try { + return this.input.readByte(); + } + catch (EOFException e) { + throw new IllegalStateException(e); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + @Override + public int readUnsignedByte() { + try { + return this.input.readUnsignedByte(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public short readShort() { + try { + return this.input.readShort(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public int readUnsignedShort() { + try { + return this.input.readUnsignedShort(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public char readChar() { + try { + return this.input.readChar(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public int readInt() { + try { + return this.input.readInt(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public long readLong() { + try { + return this.input.readLong(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public float readFloat() { + try { + return this.input.readFloat(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public double readDouble() { + try { + return this.input.readDouble(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public String readLine() { + try { + return this.input.readLine(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public String readUTF() { + try { + return this.input.readUTF(); + } + catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + private static final class FastByteArrayOutputStream + extends ByteArrayOutputStream { + private FastByteArrayOutputStream() { + } + + void writeTo(byte[] b, int off) { + System.arraycopy(this.buf, 0, b, off, this.count); + } + } +} diff --git a/src/com/google/common/io/CharSequenceReader.java b/src/com/google/common/io/CharSequenceReader.java new file mode 100644 index 0000000..345de65 --- /dev/null +++ b/src/com/google/common/io/CharSequenceReader.java @@ -0,0 +1,106 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; + +final class CharSequenceReader +extends Reader { + private CharSequence seq; + private int pos; + private int mark; + + public CharSequenceReader(CharSequence seq) { + this.seq = Preconditions.checkNotNull(seq); + } + + private void checkOpen() throws IOException { + if (this.seq == null) { + throw new IOException("reader closed"); + } + } + + private boolean hasRemaining() { + return this.remaining() > 0; + } + + private int remaining() { + return this.seq.length() - this.pos; + } + + @Override + public synchronized int read(CharBuffer target) throws IOException { + Preconditions.checkNotNull(target); + this.checkOpen(); + if (!this.hasRemaining()) { + return -1; + } + int charsToRead = Math.min(target.remaining(), this.remaining()); + for (int i = 0; i < charsToRead; ++i) { + target.put(this.seq.charAt(this.pos++)); + } + return charsToRead; + } + + @Override + public synchronized int read() throws IOException { + this.checkOpen(); + return this.hasRemaining() ? (int)this.seq.charAt(this.pos++) : -1; + } + + @Override + public synchronized int read(char[] cbuf, int off, int len) throws IOException { + Preconditions.checkPositionIndexes(off, off + len, cbuf.length); + this.checkOpen(); + if (!this.hasRemaining()) { + return -1; + } + int charsToRead = Math.min(len, this.remaining()); + for (int i = 0; i < charsToRead; ++i) { + cbuf[off + i] = this.seq.charAt(this.pos++); + } + return charsToRead; + } + + @Override + public synchronized long skip(long n) throws IOException { + Preconditions.checkArgument(n >= 0L, "n (%s) may not be negative", n); + this.checkOpen(); + int charsToSkip = (int)Math.min((long)this.remaining(), n); + this.pos += charsToSkip; + return charsToSkip; + } + + @Override + public synchronized boolean ready() throws IOException { + this.checkOpen(); + return true; + } + + @Override + public boolean markSupported() { + return true; + } + + @Override + public synchronized void mark(int readAheadLimit) throws IOException { + Preconditions.checkArgument(readAheadLimit >= 0, "readAheadLimit (%s) may not be negative", readAheadLimit); + this.checkOpen(); + this.mark = this.pos; + } + + @Override + public synchronized void reset() throws IOException { + this.checkOpen(); + this.pos = this.mark; + } + + @Override + public synchronized void close() throws IOException { + this.seq = null; + } +} diff --git a/src/com/google/common/io/CharSink.java b/src/com/google/common/io/CharSink.java new file mode 100644 index 0000000..c8818cc --- /dev/null +++ b/src/com/google/common/io/CharSink.java @@ -0,0 +1,80 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import com.google.common.io.CharStreams; +import com.google.common.io.Closer; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; + +public abstract class CharSink { + protected CharSink() { + } + + public abstract Writer openStream() throws IOException; + + public Writer openBufferedStream() throws IOException { + Writer writer = this.openStream(); + return writer instanceof BufferedWriter ? (BufferedWriter)writer : new BufferedWriter(writer); + } + + public void write(CharSequence charSequence) throws IOException { + Preconditions.checkNotNull(charSequence); + Closer closer = Closer.create(); + try { + Writer out = closer.register(this.openStream()); + out.append(charSequence); + out.flush(); + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public void writeLines(Iterable lines) throws IOException { + this.writeLines(lines, System.getProperty("line.separator")); + } + + public void writeLines(Iterable lines, String lineSeparator) throws IOException { + Preconditions.checkNotNull(lines); + Preconditions.checkNotNull(lineSeparator); + Closer closer = Closer.create(); + try { + Writer out = closer.register(this.openBufferedStream()); + for (CharSequence charSequence : lines) { + out.append(charSequence).append(lineSeparator); + } + out.flush(); + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public long writeFrom(Readable readable) throws IOException { + Preconditions.checkNotNull(readable); + Closer closer = Closer.create(); + try { + Writer out = closer.register(this.openStream()); + long written = CharStreams.copy(readable, out); + out.flush(); + long l = written; + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } +} diff --git a/src/com/google/common/io/CharSource.java b/src/com/google/common/io/CharSource.java new file mode 100644 index 0000000..6f9a67e --- /dev/null +++ b/src/com/google/common/io/CharSource.java @@ -0,0 +1,291 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Ascii; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.io.CharSequenceReader; +import com.google.common.io.CharSink; +import com.google.common.io.CharStreams; +import com.google.common.io.Closer; +import com.google.common.io.LineProcessor; +import com.google.common.io.MultiReader; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + +public abstract class CharSource { + protected CharSource() { + } + + public abstract Reader openStream() throws IOException; + + public BufferedReader openBufferedStream() throws IOException { + Reader reader = this.openStream(); + return reader instanceof BufferedReader ? (BufferedReader)reader : new BufferedReader(reader); + } + + public long copyTo(Appendable appendable) throws IOException { + Preconditions.checkNotNull(appendable); + Closer closer = Closer.create(); + try { + Reader reader = closer.register(this.openStream()); + long l = CharStreams.copy(reader, appendable); + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public long copyTo(CharSink sink) throws IOException { + Preconditions.checkNotNull(sink); + Closer closer = Closer.create(); + try { + Reader reader = closer.register(this.openStream()); + Writer writer = closer.register(sink.openStream()); + long l = CharStreams.copy(reader, writer); + return l; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public String read() throws IOException { + Closer closer = Closer.create(); + try { + Reader reader = closer.register(this.openStream()); + String string = CharStreams.toString(reader); + return string; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + @Nullable + public String readFirstLine() throws IOException { + Closer closer = Closer.create(); + try { + BufferedReader reader = closer.register(this.openBufferedStream()); + String string = reader.readLine(); + return string; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public ImmutableList readLines() throws IOException { + Closer closer = Closer.create(); + try { + String line; + BufferedReader reader = closer.register(this.openBufferedStream()); + ArrayList result = Lists.newArrayList(); + while ((line = reader.readLine()) != null) { + result.add(line); + } + ImmutableList immutableList = ImmutableList.copyOf(result); + return immutableList; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + @Beta + public T readLines(LineProcessor processor) throws IOException { + Preconditions.checkNotNull(processor); + Closer closer = Closer.create(); + try { + Reader reader = closer.register(this.openStream()); + T t = CharStreams.readLines(reader, processor); + return t; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public boolean isEmpty() throws IOException { + Closer closer = Closer.create(); + try { + Reader reader = closer.register(this.openStream()); + boolean bl = reader.read() == -1; + return bl; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public static CharSource concat(Iterable sources) { + return new ConcatenatedCharSource(sources); + } + + public static CharSource concat(Iterator sources) { + return CharSource.concat(ImmutableList.copyOf(sources)); + } + + public static CharSource concat(CharSource ... sources) { + return CharSource.concat(ImmutableList.copyOf(sources)); + } + + public static CharSource wrap(CharSequence charSequence) { + return new CharSequenceCharSource(charSequence); + } + + public static CharSource empty() { + return EmptyCharSource.INSTANCE; + } + + private static final class ConcatenatedCharSource + extends CharSource { + private final Iterable sources; + + ConcatenatedCharSource(Iterable sources) { + this.sources = Preconditions.checkNotNull(sources); + } + + @Override + public Reader openStream() throws IOException { + return new MultiReader(this.sources.iterator()); + } + + @Override + public boolean isEmpty() throws IOException { + for (CharSource charSource : this.sources) { + if (charSource.isEmpty()) continue; + return false; + } + return true; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.sources)); + return new StringBuilder(19 + string.length()).append("CharSource.concat(").append(string).append(")").toString(); + } + } + + private static final class EmptyCharSource + extends CharSequenceCharSource { + private static final EmptyCharSource INSTANCE = new EmptyCharSource(); + + private EmptyCharSource() { + super(""); + } + + @Override + public String toString() { + return "CharSource.empty()"; + } + } + + private static class CharSequenceCharSource + extends CharSource { + private static final Splitter LINE_SPLITTER = Splitter.on(Pattern.compile("\r\n|\n|\r")); + private final CharSequence seq; + + protected CharSequenceCharSource(CharSequence seq) { + this.seq = Preconditions.checkNotNull(seq); + } + + @Override + public Reader openStream() { + return new CharSequenceReader(this.seq); + } + + @Override + public String read() { + return this.seq.toString(); + } + + @Override + public boolean isEmpty() { + return this.seq.length() == 0; + } + + private Iterable lines() { + return new Iterable(){ + + @Override + public Iterator iterator() { + return new AbstractIterator(){ + Iterator lines; + { + this.lines = LINE_SPLITTER.split(CharSequenceCharSource.this.seq).iterator(); + } + + @Override + protected String computeNext() { + if (this.lines.hasNext()) { + String next = this.lines.next(); + if (this.lines.hasNext() || !next.isEmpty()) { + return next; + } + } + return (String)this.endOfData(); + } + }; + } + }; + } + + @Override + public String readFirstLine() { + Iterator lines = this.lines().iterator(); + return lines.hasNext() ? lines.next() : null; + } + + @Override + public ImmutableList readLines() { + return ImmutableList.copyOf(this.lines()); + } + + @Override + public T readLines(LineProcessor processor) throws IOException { + for (String line : this.lines()) { + if (!processor.processLine(line)) break; + } + return processor.getResult(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(Ascii.truncate(this.seq, 30, "..."))); + return new StringBuilder(17 + string.length()).append("CharSource.wrap(").append(string).append(")").toString(); + } + } +} diff --git a/src/com/google/common/io/CharStreams.java b/src/com/google/common/io/CharStreams.java new file mode 100644 index 0000000..1877ffa --- /dev/null +++ b/src/com/google/common/io/CharStreams.java @@ -0,0 +1,183 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.io.AppendableWriter; +import com.google.common.io.LineProcessor; +import com.google.common.io.LineReader; +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.nio.CharBuffer; +import java.util.ArrayList; +import java.util.List; + +@Beta +public final class CharStreams { + private static final int BUF_SIZE = 2048; + + private CharStreams() { + } + + public static long copy(Readable from, Appendable to) throws IOException { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + CharBuffer buf = CharBuffer.allocate(2048); + long total = 0L; + while (from.read(buf) != -1) { + buf.flip(); + to.append(buf); + total += (long)buf.remaining(); + buf.clear(); + } + return total; + } + + public static String toString(Readable r) throws IOException { + return CharStreams.toStringBuilder(r).toString(); + } + + private static StringBuilder toStringBuilder(Readable r) throws IOException { + StringBuilder sb = new StringBuilder(); + CharStreams.copy(r, sb); + return sb; + } + + public static List readLines(Readable r) throws IOException { + String line; + ArrayList result = new ArrayList(); + LineReader lineReader = new LineReader(r); + while ((line = lineReader.readLine()) != null) { + result.add(line); + } + return result; + } + + public static T readLines(Readable readable, LineProcessor processor) throws IOException { + String line; + Preconditions.checkNotNull(readable); + Preconditions.checkNotNull(processor); + LineReader lineReader = new LineReader(readable); + while ((line = lineReader.readLine()) != null && processor.processLine(line)) { + } + return processor.getResult(); + } + + public static void skipFully(Reader reader, long n) throws IOException { + Preconditions.checkNotNull(reader); + while (n > 0L) { + long amt = reader.skip(n); + if (amt == 0L) { + if (reader.read() == -1) { + throw new EOFException(); + } + --n; + continue; + } + n -= amt; + } + } + + public static Writer nullWriter() { + return NullWriter.INSTANCE; + } + + public static Writer asWriter(Appendable target) { + if (target instanceof Writer) { + return (Writer)target; + } + return new AppendableWriter(target); + } + + static Reader asReader(final Readable readable) { + Preconditions.checkNotNull(readable); + if (readable instanceof Reader) { + return (Reader)readable; + } + return new Reader(){ + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + return this.read(CharBuffer.wrap(cbuf, off, len)); + } + + @Override + public int read(CharBuffer target) throws IOException { + return readable.read(target); + } + + @Override + public void close() throws IOException { + if (readable instanceof Closeable) { + ((Closeable)((Object)readable)).close(); + } + } + }; + } + + private static final class NullWriter + extends Writer { + private static final NullWriter INSTANCE = new NullWriter(); + + private NullWriter() { + } + + @Override + public void write(int c) { + } + + @Override + public void write(char[] cbuf) { + Preconditions.checkNotNull(cbuf); + } + + @Override + public void write(char[] cbuf, int off, int len) { + Preconditions.checkPositionIndexes(off, off + len, cbuf.length); + } + + @Override + public void write(String str) { + Preconditions.checkNotNull(str); + } + + @Override + public void write(String str, int off, int len) { + Preconditions.checkPositionIndexes(off, off + len, str.length()); + } + + @Override + public Writer append(CharSequence csq) { + Preconditions.checkNotNull(csq); + return this; + } + + @Override + public Writer append(CharSequence csq, int start, int end) { + Preconditions.checkPositionIndexes(start, end, csq.length()); + return this; + } + + @Override + public Writer append(char c) { + return this; + } + + @Override + public void flush() { + } + + @Override + public void close() { + } + + public String toString() { + return "CharStreams.nullWriter()"; + } + } +} diff --git a/src/com/google/common/io/Closeables.java b/src/com/google/common/io/Closeables.java new file mode 100644 index 0000000..b9f863a --- /dev/null +++ b/src/com/google/common/io/Closeables.java @@ -0,0 +1,56 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +@Beta +public final class Closeables { + @VisibleForTesting + static final Logger logger = Logger.getLogger(Closeables.class.getName()); + + private Closeables() { + } + + public static void close(@Nullable Closeable closeable, boolean swallowIOException) throws IOException { + if (closeable == null) { + return; + } + try { + closeable.close(); + } + catch (IOException e) { + if (swallowIOException) { + logger.log(Level.WARNING, "IOException thrown while closing Closeable.", e); + } + throw e; + } + } + + public static void closeQuietly(@Nullable InputStream inputStream) { + try { + Closeables.close(inputStream, true); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } + + public static void closeQuietly(@Nullable Reader reader) { + try { + Closeables.close(reader, true); + } + catch (IOException impossible) { + throw new AssertionError((Object)impossible); + } + } +} diff --git a/src/com/google/common/io/Closer.java b/src/com/google/common/io/Closer.java new file mode 100644 index 0000000..834fc6d --- /dev/null +++ b/src/com/google/common/io/Closer.java @@ -0,0 +1,144 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.logging.Level; +import javax.annotation.Nullable; + +@Beta +public final class Closer +implements Closeable { + private static final Suppressor SUPPRESSOR = SuppressingSuppressor.isAvailable() ? SuppressingSuppressor.INSTANCE : LoggingSuppressor.INSTANCE; + @VisibleForTesting + final Suppressor suppressor; + private final Deque stack = new ArrayDeque(4); + private Throwable thrown; + + public static Closer create() { + return new Closer(SUPPRESSOR); + } + + @VisibleForTesting + Closer(Suppressor suppressor) { + this.suppressor = Preconditions.checkNotNull(suppressor); + } + + public C register(@Nullable C closeable) { + if (closeable != null) { + this.stack.addFirst(closeable); + } + return closeable; + } + + public RuntimeException rethrow(Throwable e) throws IOException { + Preconditions.checkNotNull(e); + this.thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + throw new RuntimeException(e); + } + + public RuntimeException rethrow(Throwable e, Class declaredType) throws IOException, X { + Preconditions.checkNotNull(e); + this.thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + Throwables.propagateIfPossible(e, declaredType); + throw new RuntimeException(e); + } + + public RuntimeException rethrow(Throwable e, Class declaredType1, Class declaredType2) throws IOException, X1, X2 { + Preconditions.checkNotNull(e); + this.thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + Throwables.propagateIfPossible(e, declaredType1, declaredType2); + throw new RuntimeException(e); + } + + @Override + public void close() throws IOException { + Throwable throwable = this.thrown; + while (!this.stack.isEmpty()) { + Closeable closeable = this.stack.removeFirst(); + try { + closeable.close(); + } + catch (Throwable e) { + if (throwable == null) { + throwable = e; + continue; + } + this.suppressor.suppress(closeable, throwable, e); + } + } + if (this.thrown == null && throwable != null) { + Throwables.propagateIfPossible(throwable, IOException.class); + throw new AssertionError((Object)throwable); + } + } + + @VisibleForTesting + static final class SuppressingSuppressor + implements Suppressor { + static final SuppressingSuppressor INSTANCE = new SuppressingSuppressor(); + static final Method addSuppressed = SuppressingSuppressor.getAddSuppressed(); + + SuppressingSuppressor() { + } + + static boolean isAvailable() { + return addSuppressed != null; + } + + private static Method getAddSuppressed() { + try { + return Throwable.class.getMethod("addSuppressed", Throwable.class); + } + catch (Throwable e) { + return null; + } + } + + @Override + public void suppress(Closeable closeable, Throwable thrown, Throwable suppressed) { + if (thrown == suppressed) { + return; + } + try { + addSuppressed.invoke(thrown, suppressed); + } + catch (Throwable e) { + LoggingSuppressor.INSTANCE.suppress(closeable, thrown, suppressed); + } + } + } + + @VisibleForTesting + static final class LoggingSuppressor + implements Suppressor { + static final LoggingSuppressor INSTANCE = new LoggingSuppressor(); + + LoggingSuppressor() { + } + + @Override + public void suppress(Closeable closeable, Throwable thrown, Throwable suppressed) { + String string = String.valueOf(String.valueOf(closeable)); + Closeables.logger.log(Level.WARNING, new StringBuilder(42 + string.length()).append("Suppressing exception thrown when closing ").append(string).toString(), suppressed); + } + } + + @VisibleForTesting + static interface Suppressor { + public void suppress(Closeable var1, Throwable var2, Throwable var3); + } +} diff --git a/src/com/google/common/io/CountingInputStream.java b/src/com/google/common/io/CountingInputStream.java new file mode 100644 index 0000000..9326c37 --- /dev/null +++ b/src/com/google/common/io/CountingInputStream.java @@ -0,0 +1,68 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.Nullable; + +@Beta +public final class CountingInputStream +extends FilterInputStream { + private long count; + private long mark = -1L; + + public CountingInputStream(@Nullable InputStream in) { + super(in); + } + + public long getCount() { + return this.count; + } + + @Override + public int read() throws IOException { + int result = this.in.read(); + if (result != -1) { + ++this.count; + } + return result; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int result = this.in.read(b, off, len); + if (result != -1) { + this.count += (long)result; + } + return result; + } + + @Override + public long skip(long n) throws IOException { + long result = this.in.skip(n); + this.count += result; + return result; + } + + @Override + public synchronized void mark(int readlimit) { + this.in.mark(readlimit); + this.mark = this.count; + } + + @Override + public synchronized void reset() throws IOException { + if (!this.in.markSupported()) { + throw new IOException("Mark not supported"); + } + if (this.mark == -1L) { + throw new IOException("Mark not set"); + } + this.in.reset(); + this.count = this.mark; + } +} diff --git a/src/com/google/common/io/CountingOutputStream.java b/src/com/google/common/io/CountingOutputStream.java new file mode 100644 index 0000000..4e4d3da --- /dev/null +++ b/src/com/google/common/io/CountingOutputStream.java @@ -0,0 +1,41 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.annotation.Nullable; + +@Beta +public final class CountingOutputStream +extends FilterOutputStream { + private long count; + + public CountingOutputStream(@Nullable OutputStream out) { + super(out); + } + + public long getCount() { + return this.count; + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + this.out.write(b, off, len); + this.count += (long)len; + } + + @Override + public void write(int b) throws IOException { + this.out.write(b); + ++this.count; + } + + @Override + public void close() throws IOException { + this.out.close(); + } +} diff --git a/src/com/google/common/io/FileBackedOutputStream.java b/src/com/google/common/io/FileBackedOutputStream.java new file mode 100644 index 0000000..1b51a26 --- /dev/null +++ b/src/com/google/common/io/FileBackedOutputStream.java @@ -0,0 +1,157 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.io.ByteSource; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +@Beta +public final class FileBackedOutputStream +extends OutputStream { + private final int fileThreshold; + private final boolean resetOnFinalize; + private final ByteSource source; + private OutputStream out; + private MemoryOutput memory; + private File file; + + @VisibleForTesting + synchronized File getFile() { + return this.file; + } + + public FileBackedOutputStream(int fileThreshold) { + this(fileThreshold, false); + } + + public FileBackedOutputStream(int fileThreshold, boolean resetOnFinalize) { + this.fileThreshold = fileThreshold; + this.resetOnFinalize = resetOnFinalize; + this.memory = new MemoryOutput(); + this.out = this.memory; + this.source = resetOnFinalize ? new ByteSource(){ + + @Override + public InputStream openStream() throws IOException { + return FileBackedOutputStream.this.openInputStream(); + } + + protected void finalize() { + try { + FileBackedOutputStream.this.reset(); + } + catch (Throwable t) { + t.printStackTrace(System.err); + } + } + } : new ByteSource(){ + + @Override + public InputStream openStream() throws IOException { + return FileBackedOutputStream.this.openInputStream(); + } + }; + } + + public ByteSource asByteSource() { + return this.source; + } + + private synchronized InputStream openInputStream() throws IOException { + if (this.file != null) { + return new FileInputStream(this.file); + } + return new ByteArrayInputStream(this.memory.getBuffer(), 0, this.memory.getCount()); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public synchronized void reset() throws IOException { + try { + this.close(); + } + finally { + if (this.memory == null) { + this.memory = new MemoryOutput(); + } else { + this.memory.reset(); + } + this.out = this.memory; + if (this.file != null) { + File deleteMe = this.file; + this.file = null; + if (!deleteMe.delete()) { + String string = String.valueOf(String.valueOf(deleteMe)); + throw new IOException(new StringBuilder(18 + string.length()).append("Could not delete: ").append(string).toString()); + } + } + } + } + + @Override + public synchronized void write(int b) throws IOException { + this.update(1); + this.out.write(b); + } + + @Override + public synchronized void write(byte[] b) throws IOException { + this.write(b, 0, b.length); + } + + @Override + public synchronized void write(byte[] b, int off, int len) throws IOException { + this.update(len); + this.out.write(b, off, len); + } + + @Override + public synchronized void close() throws IOException { + this.out.close(); + } + + @Override + public synchronized void flush() throws IOException { + this.out.flush(); + } + + private void update(int len) throws IOException { + if (this.file == null && this.memory.getCount() + len > this.fileThreshold) { + File temp = File.createTempFile("FileBackedOutputStream", null); + if (this.resetOnFinalize) { + temp.deleteOnExit(); + } + FileOutputStream transfer = new FileOutputStream(temp); + transfer.write(this.memory.getBuffer(), 0, this.memory.getCount()); + transfer.flush(); + this.out = transfer; + this.file = temp; + this.memory = null; + } + } + + private static class MemoryOutput + extends ByteArrayOutputStream { + private MemoryOutput() { + } + + byte[] getBuffer() { + return this.buf; + } + + int getCount() { + return this.count; + } + } +} diff --git a/src/com/google/common/io/FileWriteMode.java b/src/com/google/common/io/FileWriteMode.java new file mode 100644 index 0000000..92f39e2 --- /dev/null +++ b/src/com/google/common/io/FileWriteMode.java @@ -0,0 +1,9 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +public enum FileWriteMode { + APPEND; + +} diff --git a/src/com/google/common/io/Files.java b/src/com/google/common/io/Files.java new file mode 100644 index 0000000..39d6748 --- /dev/null +++ b/src/com/google/common/io/Files.java @@ -0,0 +1,457 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.TreeTraverser; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.io.ByteProcessor; +import com.google.common.io.ByteSink; +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; +import com.google.common.io.CharSink; +import com.google.common.io.CharSource; +import com.google.common.io.Closer; +import com.google.common.io.FileWriteMode; +import com.google.common.io.LineProcessor; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.RandomAccessFile; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Beta +public final class Files { + private static final int TEMP_DIR_ATTEMPTS = 10000; + private static final TreeTraverser FILE_TREE_TRAVERSER = new TreeTraverser(){ + + @Override + public Iterable children(File file) { + File[] files; + if (file.isDirectory() && (files = file.listFiles()) != null) { + return Collections.unmodifiableList(Arrays.asList(files)); + } + return Collections.emptyList(); + } + + public String toString() { + return "Files.fileTreeTraverser()"; + } + }; + + private Files() { + } + + public static BufferedReader newReader(File file, Charset charset) throws FileNotFoundException { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(charset); + return new BufferedReader(new InputStreamReader((InputStream)new FileInputStream(file), charset)); + } + + public static BufferedWriter newWriter(File file, Charset charset) throws FileNotFoundException { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(charset); + return new BufferedWriter(new OutputStreamWriter((OutputStream)new FileOutputStream(file), charset)); + } + + public static ByteSource asByteSource(File file) { + return new FileByteSource(file); + } + + static byte[] readFile(InputStream in, long expectedSize) throws IOException { + if (expectedSize > Integer.MAX_VALUE) { + long l = expectedSize; + throw new OutOfMemoryError(new StringBuilder(68).append("file is too large to fit in a byte array: ").append(l).append(" bytes").toString()); + } + return expectedSize == 0L ? ByteStreams.toByteArray(in) : ByteStreams.toByteArray(in, (int)expectedSize); + } + + public static ByteSink asByteSink(File file, FileWriteMode ... modes) { + return new FileByteSink(file, modes); + } + + public static CharSource asCharSource(File file, Charset charset) { + return Files.asByteSource(file).asCharSource(charset); + } + + public static CharSink asCharSink(File file, Charset charset, FileWriteMode ... modes) { + return Files.asByteSink(file, modes).asCharSink(charset); + } + + private static FileWriteMode[] modes(boolean append) { + FileWriteMode[] fileWriteModeArray; + if (append) { + FileWriteMode[] fileWriteModeArray2 = new FileWriteMode[1]; + fileWriteModeArray = fileWriteModeArray2; + fileWriteModeArray2[0] = FileWriteMode.APPEND; + } else { + fileWriteModeArray = new FileWriteMode[]{}; + } + return fileWriteModeArray; + } + + public static byte[] toByteArray(File file) throws IOException { + return Files.asByteSource(file).read(); + } + + public static String toString(File file, Charset charset) throws IOException { + return Files.asCharSource(file, charset).read(); + } + + public static void write(byte[] from, File to) throws IOException { + Files.asByteSink(to, new FileWriteMode[0]).write(from); + } + + public static void copy(File from, OutputStream to) throws IOException { + Files.asByteSource(from).copyTo(to); + } + + public static void copy(File from, File to) throws IOException { + Preconditions.checkArgument(!from.equals(to), "Source %s and destination %s must be different", from, to); + Files.asByteSource(from).copyTo(Files.asByteSink(to, new FileWriteMode[0])); + } + + public static void write(CharSequence from, File to, Charset charset) throws IOException { + Files.asCharSink(to, charset, new FileWriteMode[0]).write(from); + } + + public static void append(CharSequence from, File to, Charset charset) throws IOException { + Files.write(from, to, charset, true); + } + + private static void write(CharSequence from, File to, Charset charset, boolean append) throws IOException { + Files.asCharSink(to, charset, Files.modes(append)).write(from); + } + + public static void copy(File from, Charset charset, Appendable to) throws IOException { + Files.asCharSource(from, charset).copyTo(to); + } + + public static boolean equal(File file1, File file2) throws IOException { + Preconditions.checkNotNull(file1); + Preconditions.checkNotNull(file2); + if (file1 == file2 || file1.equals(file2)) { + return true; + } + long len1 = file1.length(); + long len2 = file2.length(); + if (len1 != 0L && len2 != 0L && len1 != len2) { + return false; + } + return Files.asByteSource(file1).contentEquals(Files.asByteSource(file2)); + } + + public static File createTempDir() { + int n; + String string; + File baseDir = new File(System.getProperty("java.io.tmpdir")); + long l = System.currentTimeMillis(); + String baseName = new StringBuilder(21).append(l).append("-").toString(); + int counter = 0; + while (counter < 10000) { + string = String.valueOf(String.valueOf(baseName)); + n = counter++; + File tempDir = new File(baseDir, new StringBuilder(11 + string.length()).append(string).append(n).toString()); + if (!tempDir.mkdir()) continue; + return tempDir; + } + String string2 = String.valueOf(String.valueOf("Failed to create directory within 10000 attempts (tried ")); + String string3 = String.valueOf(String.valueOf(baseName)); + string = String.valueOf(String.valueOf(baseName)); + n = 9999; + throw new IllegalStateException(new StringBuilder(17 + string2.length() + string3.length() + string.length()).append(string2).append(string3).append("0 to ").append(string).append(n).append(")").toString()); + } + + public static void touch(File file) throws IOException { + Preconditions.checkNotNull(file); + if (!file.createNewFile() && !file.setLastModified(System.currentTimeMillis())) { + String string = String.valueOf(String.valueOf(file)); + throw new IOException(new StringBuilder(38 + string.length()).append("Unable to update modification time of ").append(string).toString()); + } + } + + public static void createParentDirs(File file) throws IOException { + Preconditions.checkNotNull(file); + File parent = file.getCanonicalFile().getParentFile(); + if (parent == null) { + return; + } + parent.mkdirs(); + if (!parent.isDirectory()) { + String string = String.valueOf(String.valueOf(file)); + throw new IOException(new StringBuilder(39 + string.length()).append("Unable to create parent directories of ").append(string).toString()); + } + } + + public static void move(File from, File to) throws IOException { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + Preconditions.checkArgument(!from.equals(to), "Source %s and destination %s must be different", from, to); + if (!from.renameTo(to)) { + Files.copy(from, to); + if (!from.delete()) { + if (!to.delete()) { + String string = String.valueOf(String.valueOf(to)); + throw new IOException(new StringBuilder(17 + string.length()).append("Unable to delete ").append(string).toString()); + } + String string = String.valueOf(String.valueOf(from)); + throw new IOException(new StringBuilder(17 + string.length()).append("Unable to delete ").append(string).toString()); + } + } + } + + public static String readFirstLine(File file, Charset charset) throws IOException { + return Files.asCharSource(file, charset).readFirstLine(); + } + + public static List readLines(File file, Charset charset) throws IOException { + return Files.readLines(file, charset, new LineProcessor>(){ + final List result = Lists.newArrayList(); + + @Override + public boolean processLine(String line) { + this.result.add(line); + return true; + } + + @Override + public List getResult() { + return this.result; + } + }); + } + + public static T readLines(File file, Charset charset, LineProcessor callback) throws IOException { + return Files.asCharSource(file, charset).readLines(callback); + } + + public static T readBytes(File file, ByteProcessor processor) throws IOException { + return Files.asByteSource(file).read(processor); + } + + public static HashCode hash(File file, HashFunction hashFunction) throws IOException { + return Files.asByteSource(file).hash(hashFunction); + } + + public static MappedByteBuffer map(File file) throws IOException { + Preconditions.checkNotNull(file); + return Files.map(file, FileChannel.MapMode.READ_ONLY); + } + + public static MappedByteBuffer map(File file, FileChannel.MapMode mode) throws IOException { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(mode); + if (!file.exists()) { + throw new FileNotFoundException(file.toString()); + } + return Files.map(file, mode, file.length()); + } + + public static MappedByteBuffer map(File file, FileChannel.MapMode mode, long size) throws FileNotFoundException, IOException { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(mode); + Closer closer = Closer.create(); + try { + RandomAccessFile raf = closer.register(new RandomAccessFile(file, mode == FileChannel.MapMode.READ_ONLY ? "r" : "rw")); + MappedByteBuffer mappedByteBuffer = Files.map(raf, mode, size); + return mappedByteBuffer; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + private static MappedByteBuffer map(RandomAccessFile raf, FileChannel.MapMode mode, long size) throws IOException { + Closer closer = Closer.create(); + try { + FileChannel channel = closer.register(raf.getChannel()); + MappedByteBuffer mappedByteBuffer = channel.map(mode, 0L, size); + return mappedByteBuffer; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public static String simplifyPath(String pathname) { + Preconditions.checkNotNull(pathname); + if (pathname.length() == 0) { + return "."; + } + Iterable components = Splitter.on('/').omitEmptyStrings().split(pathname); + ArrayList path = new ArrayList(); + for (String component : components) { + if (component.equals(".")) continue; + if (component.equals("..")) { + if (path.size() > 0 && !((String)path.get(path.size() - 1)).equals("..")) { + path.remove(path.size() - 1); + continue; + } + path.add(".."); + continue; + } + path.add(component); + } + String result = Joiner.on('/').join(path); + if (pathname.charAt(0) == '/') { + String string = String.valueOf(result); + String string2 = result = string.length() != 0 ? "/".concat(string) : new String("/"); + } + while (result.startsWith("/../")) { + result = result.substring(3); + } + if (result.equals("/..")) { + result = "/"; + } else if ("".equals(result)) { + result = "."; + } + return result; + } + + public static String getFileExtension(String fullName) { + Preconditions.checkNotNull(fullName); + String fileName = new File(fullName).getName(); + int dotIndex = fileName.lastIndexOf(46); + return dotIndex == -1 ? "" : fileName.substring(dotIndex + 1); + } + + public static String getNameWithoutExtension(String file) { + Preconditions.checkNotNull(file); + String fileName = new File(file).getName(); + int dotIndex = fileName.lastIndexOf(46); + return dotIndex == -1 ? fileName : fileName.substring(0, dotIndex); + } + + public static TreeTraverser fileTreeTraverser() { + return FILE_TREE_TRAVERSER; + } + + public static Predicate isDirectory() { + return FilePredicate.IS_DIRECTORY; + } + + public static Predicate isFile() { + return FilePredicate.IS_FILE; + } + + private static enum FilePredicate implements Predicate + { + IS_DIRECTORY{ + + @Override + public boolean apply(File file) { + return file.isDirectory(); + } + + public String toString() { + return "Files.isDirectory()"; + } + } + , + IS_FILE{ + + @Override + public boolean apply(File file) { + return file.isFile(); + } + + public String toString() { + return "Files.isFile()"; + } + }; + + } + + private static final class FileByteSink + extends ByteSink { + private final File file; + private final ImmutableSet modes; + + private FileByteSink(File file, FileWriteMode ... modes) { + this.file = Preconditions.checkNotNull(file); + this.modes = ImmutableSet.copyOf(modes); + } + + @Override + public FileOutputStream openStream() throws IOException { + return new FileOutputStream(this.file, this.modes.contains((Object)FileWriteMode.APPEND)); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.file)); + String string2 = String.valueOf(String.valueOf(this.modes)); + return new StringBuilder(20 + string.length() + string2.length()).append("Files.asByteSink(").append(string).append(", ").append(string2).append(")").toString(); + } + } + + private static final class FileByteSource + extends ByteSource { + private final File file; + + private FileByteSource(File file) { + this.file = Preconditions.checkNotNull(file); + } + + @Override + public FileInputStream openStream() throws IOException { + return new FileInputStream(this.file); + } + + @Override + public long size() throws IOException { + if (!this.file.isFile()) { + throw new FileNotFoundException(this.file.toString()); + } + return this.file.length(); + } + + @Override + public byte[] read() throws IOException { + Closer closer = Closer.create(); + try { + FileInputStream in = closer.register(this.openStream()); + byte[] byArray = Files.readFile(in, in.getChannel().size()); + return byArray; + } + catch (Throwable e) { + throw closer.rethrow(e); + } + finally { + closer.close(); + } + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.file)); + return new StringBuilder(20 + string.length()).append("Files.asByteSource(").append(string).append(")").toString(); + } + } +} diff --git a/src/com/google/common/io/Flushables.java b/src/com/google/common/io/Flushables.java new file mode 100644 index 0000000..fc322cb --- /dev/null +++ b/src/com/google/common/io/Flushables.java @@ -0,0 +1,39 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.Flushable; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Beta +public final class Flushables { + private static final Logger logger = Logger.getLogger(Flushables.class.getName()); + + private Flushables() { + } + + public static void flush(Flushable flushable, boolean swallowIOException) throws IOException { + try { + flushable.flush(); + } + catch (IOException e) { + if (swallowIOException) { + logger.log(Level.WARNING, "IOException thrown while flushing Flushable.", e); + } + throw e; + } + } + + public static void flushQuietly(Flushable flushable) { + try { + Flushables.flush(flushable, true); + } + catch (IOException e) { + logger.log(Level.SEVERE, "IOException should not have been thrown.", e); + } + } +} diff --git a/src/com/google/common/io/GwtWorkarounds.java b/src/com/google/common/io/GwtWorkarounds.java new file mode 100644 index 0000000..39580f5 --- /dev/null +++ b/src/com/google/common/io/GwtWorkarounds.java @@ -0,0 +1,190 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +@GwtCompatible(emulated=true) +final class GwtWorkarounds { + private GwtWorkarounds() { + } + + @GwtIncompatible(value="Reader") + static CharInput asCharInput(final Reader reader) { + Preconditions.checkNotNull(reader); + return new CharInput(){ + + @Override + public int read() throws IOException { + return reader.read(); + } + + @Override + public void close() throws IOException { + reader.close(); + } + }; + } + + static CharInput asCharInput(final CharSequence chars) { + Preconditions.checkNotNull(chars); + return new CharInput(){ + int index = 0; + + @Override + public int read() { + if (this.index < chars.length()) { + return chars.charAt(this.index++); + } + return -1; + } + + @Override + public void close() { + this.index = chars.length(); + } + }; + } + + @GwtIncompatible(value="InputStream") + static InputStream asInputStream(final ByteInput input) { + Preconditions.checkNotNull(input); + return new InputStream(){ + + @Override + public int read() throws IOException { + return input.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + Preconditions.checkNotNull(b); + Preconditions.checkPositionIndexes(off, off + len, b.length); + if (len == 0) { + return 0; + } + int firstByte = this.read(); + if (firstByte == -1) { + return -1; + } + b[off] = (byte)firstByte; + for (int dst = 1; dst < len; ++dst) { + int readByte = this.read(); + if (readByte == -1) { + return dst; + } + b[off + dst] = (byte)readByte; + } + return len; + } + + @Override + public void close() throws IOException { + input.close(); + } + }; + } + + @GwtIncompatible(value="OutputStream") + static OutputStream asOutputStream(final ByteOutput output) { + Preconditions.checkNotNull(output); + return new OutputStream(){ + + @Override + public void write(int b) throws IOException { + output.write((byte)b); + } + + @Override + public void flush() throws IOException { + output.flush(); + } + + @Override + public void close() throws IOException { + output.close(); + } + }; + } + + @GwtIncompatible(value="Writer") + static CharOutput asCharOutput(final Writer writer) { + Preconditions.checkNotNull(writer); + return new CharOutput(){ + + @Override + public void write(char c) throws IOException { + writer.append(c); + } + + @Override + public void flush() throws IOException { + writer.flush(); + } + + @Override + public void close() throws IOException { + writer.close(); + } + }; + } + + static CharOutput stringBuilderOutput(int initialSize) { + final StringBuilder builder = new StringBuilder(initialSize); + return new CharOutput(){ + + @Override + public void write(char c) { + builder.append(c); + } + + @Override + public void flush() { + } + + @Override + public void close() { + } + + public String toString() { + return builder.toString(); + } + }; + } + + static interface CharOutput { + public void write(char var1) throws IOException; + + public void flush() throws IOException; + + public void close() throws IOException; + } + + static interface ByteOutput { + public void write(byte var1) throws IOException; + + public void flush() throws IOException; + + public void close() throws IOException; + } + + static interface ByteInput { + public int read() throws IOException; + + public void close() throws IOException; + } + + static interface CharInput { + public int read() throws IOException; + + public void close() throws IOException; + } +} diff --git a/src/com/google/common/io/InputSupplier.java b/src/com/google/common/io/InputSupplier.java new file mode 100644 index 0000000..d359b68 --- /dev/null +++ b/src/com/google/common/io/InputSupplier.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import java.io.IOException; + +@Deprecated +public interface InputSupplier { + public T getInput() throws IOException; +} diff --git a/src/com/google/common/io/LineBuffer.java b/src/com/google/common/io/LineBuffer.java new file mode 100644 index 0000000..b205bca --- /dev/null +++ b/src/com/google/common/io/LineBuffer.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import java.io.IOException; + +abstract class LineBuffer { + private StringBuilder line = new StringBuilder(); + private boolean sawReturn; + + LineBuffer() { + } + + protected void add(char[] cbuf, int off, int len) throws IOException { + int pos = off; + if (this.sawReturn && len > 0 && this.finishLine(cbuf[pos] == '\n')) { + ++pos; + } + int start = pos; + int end = off + len; + while (pos < end) { + switch (cbuf[pos]) { + case '\r': { + this.line.append(cbuf, start, pos - start); + this.sawReturn = true; + if (pos + 1 < end && this.finishLine(cbuf[pos + 1] == '\n')) { + ++pos; + } + start = pos + 1; + break; + } + case '\n': { + this.line.append(cbuf, start, pos - start); + this.finishLine(true); + start = pos + 1; + break; + } + } + ++pos; + } + this.line.append(cbuf, start, off + len - start); + } + + private boolean finishLine(boolean sawNewline) throws IOException { + this.handleLine(this.line.toString(), this.sawReturn ? (sawNewline ? "\r\n" : "\r") : (sawNewline ? "\n" : "")); + this.line = new StringBuilder(); + this.sawReturn = false; + return sawNewline; + } + + protected void finish() throws IOException { + if (this.sawReturn || this.line.length() > 0) { + this.finishLine(false); + } + } + + protected abstract void handleLine(String var1, String var2) throws IOException; +} diff --git a/src/com/google/common/io/LineProcessor.java b/src/com/google/common/io/LineProcessor.java new file mode 100644 index 0000000..add9ba7 --- /dev/null +++ b/src/com/google/common/io/LineProcessor.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.IOException; + +@Beta +public interface LineProcessor { + public boolean processLine(String var1) throws IOException; + + public T getResult(); +} diff --git a/src/com/google/common/io/LineReader.java b/src/com/google/common/io/LineReader.java new file mode 100644 index 0000000..91a09d0 --- /dev/null +++ b/src/com/google/common/io/LineReader.java @@ -0,0 +1,48 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.io.LineBuffer; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; +import java.util.LinkedList; +import java.util.Queue; + +@Beta +public final class LineReader { + private final Readable readable; + private final Reader reader; + private final char[] buf = new char[4096]; + private final CharBuffer cbuf = CharBuffer.wrap(this.buf); + private final Queue lines = new LinkedList(); + private final LineBuffer lineBuf = new LineBuffer(){ + + @Override + protected void handleLine(String line, String end) { + LineReader.this.lines.add(line); + } + }; + + public LineReader(Readable readable) { + this.readable = Preconditions.checkNotNull(readable); + this.reader = readable instanceof Reader ? (Reader)readable : null; + } + + public String readLine() throws IOException { + while (this.lines.peek() == null) { + int read; + this.cbuf.clear(); + int n = read = this.reader != null ? this.reader.read(this.buf, 0, this.buf.length) : this.readable.read(this.cbuf); + if (read == -1) { + this.lineBuf.finish(); + break; + } + this.lineBuf.add(this.buf, 0, read); + } + return this.lines.poll(); + } +} diff --git a/src/com/google/common/io/LittleEndianDataInputStream.java b/src/com/google/common/io/LittleEndianDataInputStream.java new file mode 100644 index 0000000..75dca09 --- /dev/null +++ b/src/com/google/common/io/LittleEndianDataInputStream.java @@ -0,0 +1,126 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.io.ByteStreams; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +@Beta +public final class LittleEndianDataInputStream +extends FilterInputStream +implements DataInput { + public LittleEndianDataInputStream(InputStream in) { + super(Preconditions.checkNotNull(in)); + } + + @Override + public String readLine() { + throw new UnsupportedOperationException("readLine is not supported"); + } + + @Override + public void readFully(byte[] b) throws IOException { + ByteStreams.readFully(this, b); + } + + @Override + public void readFully(byte[] b, int off, int len) throws IOException { + ByteStreams.readFully(this, b, off, len); + } + + @Override + public int skipBytes(int n) throws IOException { + return (int)this.in.skip(n); + } + + @Override + public int readUnsignedByte() throws IOException { + int b1 = this.in.read(); + if (0 > b1) { + throw new EOFException(); + } + return b1; + } + + @Override + public int readUnsignedShort() throws IOException { + byte b1 = this.readAndCheckByte(); + byte b2 = this.readAndCheckByte(); + return Ints.fromBytes((byte)0, (byte)0, b2, b1); + } + + @Override + public int readInt() throws IOException { + byte b1 = this.readAndCheckByte(); + byte b2 = this.readAndCheckByte(); + byte b3 = this.readAndCheckByte(); + byte b4 = this.readAndCheckByte(); + return Ints.fromBytes(b4, b3, b2, b1); + } + + @Override + public long readLong() throws IOException { + byte b1 = this.readAndCheckByte(); + byte b2 = this.readAndCheckByte(); + byte b3 = this.readAndCheckByte(); + byte b4 = this.readAndCheckByte(); + byte b5 = this.readAndCheckByte(); + byte b6 = this.readAndCheckByte(); + byte b7 = this.readAndCheckByte(); + byte b8 = this.readAndCheckByte(); + return Longs.fromBytes(b8, b7, b6, b5, b4, b3, b2, b1); + } + + @Override + public float readFloat() throws IOException { + return Float.intBitsToFloat(this.readInt()); + } + + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(this.readLong()); + } + + @Override + public String readUTF() throws IOException { + return new DataInputStream(this.in).readUTF(); + } + + @Override + public short readShort() throws IOException { + return (short)this.readUnsignedShort(); + } + + @Override + public char readChar() throws IOException { + return (char)this.readUnsignedShort(); + } + + @Override + public byte readByte() throws IOException { + return (byte)this.readUnsignedByte(); + } + + @Override + public boolean readBoolean() throws IOException { + return this.readUnsignedByte() != 0; + } + + private byte readAndCheckByte() throws IOException, EOFException { + int b1 = this.in.read(); + if (-1 == b1) { + throw new EOFException(); + } + return (byte)b1; + } +} diff --git a/src/com/google/common/io/LittleEndianDataOutputStream.java b/src/com/google/common/io/LittleEndianDataOutputStream.java new file mode 100644 index 0000000..3ab8785 --- /dev/null +++ b/src/com/google/common/io/LittleEndianDataOutputStream.java @@ -0,0 +1,95 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Longs; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +@Beta +public class LittleEndianDataOutputStream +extends FilterOutputStream +implements DataOutput { + public LittleEndianDataOutputStream(OutputStream out) { + super(new DataOutputStream(Preconditions.checkNotNull(out))); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + this.out.write(b, off, len); + } + + @Override + public void writeBoolean(boolean v) throws IOException { + ((DataOutputStream)this.out).writeBoolean(v); + } + + @Override + public void writeByte(int v) throws IOException { + ((DataOutputStream)this.out).writeByte(v); + } + + @Override + @Deprecated + public void writeBytes(String s) throws IOException { + ((DataOutputStream)this.out).writeBytes(s); + } + + @Override + public void writeChar(int v) throws IOException { + this.writeShort(v); + } + + @Override + public void writeChars(String s) throws IOException { + for (int i = 0; i < s.length(); ++i) { + this.writeChar(s.charAt(i)); + } + } + + @Override + public void writeDouble(double v) throws IOException { + this.writeLong(Double.doubleToLongBits(v)); + } + + @Override + public void writeFloat(float v) throws IOException { + this.writeInt(Float.floatToIntBits(v)); + } + + @Override + public void writeInt(int v) throws IOException { + this.out.write(0xFF & v); + this.out.write(0xFF & v >> 8); + this.out.write(0xFF & v >> 16); + this.out.write(0xFF & v >> 24); + } + + @Override + public void writeLong(long v) throws IOException { + byte[] bytes = Longs.toByteArray(Long.reverseBytes(v)); + this.write(bytes, 0, bytes.length); + } + + @Override + public void writeShort(int v) throws IOException { + this.out.write(0xFF & v); + this.out.write(0xFF & v >> 8); + } + + @Override + public void writeUTF(String str) throws IOException { + ((DataOutputStream)this.out).writeUTF(str); + } + + @Override + public void close() throws IOException { + this.out.close(); + } +} diff --git a/src/com/google/common/io/MultiInputStream.java b/src/com/google/common/io/MultiInputStream.java new file mode 100644 index 0000000..eab1ca1 --- /dev/null +++ b/src/com/google/common/io/MultiInputStream.java @@ -0,0 +1,98 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import com.google.common.io.ByteSource; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import javax.annotation.Nullable; + +final class MultiInputStream +extends InputStream { + private Iterator it; + private InputStream in; + + public MultiInputStream(Iterator it) throws IOException { + this.it = Preconditions.checkNotNull(it); + this.advance(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void close() throws IOException { + if (this.in != null) { + try { + this.in.close(); + } + finally { + this.in = null; + } + } + } + + private void advance() throws IOException { + this.close(); + if (this.it.hasNext()) { + this.in = this.it.next().openStream(); + } + } + + @Override + public int available() throws IOException { + if (this.in == null) { + return 0; + } + return this.in.available(); + } + + @Override + public boolean markSupported() { + return false; + } + + @Override + public int read() throws IOException { + if (this.in == null) { + return -1; + } + int result = this.in.read(); + if (result == -1) { + this.advance(); + return this.read(); + } + return result; + } + + @Override + public int read(@Nullable byte[] b, int off, int len) throws IOException { + if (this.in == null) { + return -1; + } + int result = this.in.read(b, off, len); + if (result == -1) { + this.advance(); + return this.read(b, off, len); + } + return result; + } + + @Override + public long skip(long n) throws IOException { + if (this.in == null || n <= 0L) { + return 0L; + } + long result = this.in.skip(n); + if (result != 0L) { + return result; + } + if (this.read() == -1) { + return 0L; + } + return 1L + this.in.skip(n - 1L); + } +} diff --git a/src/com/google/common/io/MultiReader.java b/src/com/google/common/io/MultiReader.java new file mode 100644 index 0000000..acabf57 --- /dev/null +++ b/src/com/google/common/io/MultiReader.java @@ -0,0 +1,77 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import com.google.common.io.CharSource; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; +import javax.annotation.Nullable; + +class MultiReader +extends Reader { + private final Iterator it; + private Reader current; + + MultiReader(Iterator readers) throws IOException { + this.it = readers; + this.advance(); + } + + private void advance() throws IOException { + this.close(); + if (this.it.hasNext()) { + this.current = this.it.next().openStream(); + } + } + + @Override + public int read(@Nullable char[] cbuf, int off, int len) throws IOException { + if (this.current == null) { + return -1; + } + int result = this.current.read(cbuf, off, len); + if (result == -1) { + this.advance(); + return this.read(cbuf, off, len); + } + return result; + } + + @Override + public long skip(long n) throws IOException { + Preconditions.checkArgument(n >= 0L, "n is negative"); + if (n > 0L) { + while (this.current != null) { + long result = this.current.skip(n); + if (result > 0L) { + return result; + } + this.advance(); + } + } + return 0L; + } + + @Override + public boolean ready() throws IOException { + return this.current != null && this.current.ready(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void close() throws IOException { + if (this.current != null) { + try { + this.current.close(); + } + finally { + this.current = null; + } + } + } +} diff --git a/src/com/google/common/io/OutputSupplier.java b/src/com/google/common/io/OutputSupplier.java new file mode 100644 index 0000000..ab11ba1 --- /dev/null +++ b/src/com/google/common/io/OutputSupplier.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import java.io.IOException; + +@Deprecated +public interface OutputSupplier { + public T getOutput() throws IOException; +} diff --git a/src/com/google/common/io/PatternFilenameFilter.java b/src/com/google/common/io/PatternFilenameFilter.java new file mode 100644 index 0000000..4e0483c --- /dev/null +++ b/src/com/google/common/io/PatternFilenameFilter.java @@ -0,0 +1,30 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.File; +import java.io.FilenameFilter; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + +@Beta +public final class PatternFilenameFilter +implements FilenameFilter { + private final Pattern pattern; + + public PatternFilenameFilter(String patternStr) { + this(Pattern.compile(patternStr)); + } + + public PatternFilenameFilter(Pattern pattern) { + this.pattern = Preconditions.checkNotNull(pattern); + } + + @Override + public boolean accept(@Nullable File dir, String fileName) { + return this.pattern.matcher(fileName).matches(); + } +} diff --git a/src/com/google/common/io/Resources.java b/src/com/google/common/io/Resources.java new file mode 100644 index 0000000..2c72bee --- /dev/null +++ b/src/com/google/common/io/Resources.java @@ -0,0 +1,97 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.io.ByteSource; +import com.google.common.io.CharSource; +import com.google.common.io.LineProcessor; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.List; + +@Beta +public final class Resources { + private Resources() { + } + + public static ByteSource asByteSource(URL url) { + return new UrlByteSource(url); + } + + public static CharSource asCharSource(URL url, Charset charset) { + return Resources.asByteSource(url).asCharSource(charset); + } + + public static byte[] toByteArray(URL url) throws IOException { + return Resources.asByteSource(url).read(); + } + + public static String toString(URL url, Charset charset) throws IOException { + return Resources.asCharSource(url, charset).read(); + } + + public static T readLines(URL url, Charset charset, LineProcessor callback) throws IOException { + return Resources.asCharSource(url, charset).readLines(callback); + } + + public static List readLines(URL url, Charset charset) throws IOException { + return Resources.readLines(url, charset, new LineProcessor>(){ + final List result = Lists.newArrayList(); + + @Override + public boolean processLine(String line) { + this.result.add(line); + return true; + } + + @Override + public List getResult() { + return this.result; + } + }); + } + + public static void copy(URL from, OutputStream to) throws IOException { + Resources.asByteSource(from).copyTo(to); + } + + public static URL getResource(String resourceName) { + ClassLoader loader = MoreObjects.firstNonNull(Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader()); + URL url = loader.getResource(resourceName); + Preconditions.checkArgument(url != null, "resource %s not found.", resourceName); + return url; + } + + public static URL getResource(Class contextClass, String resourceName) { + URL url = contextClass.getResource(resourceName); + Preconditions.checkArgument(url != null, "resource %s relative to %s not found.", resourceName, contextClass.getName()); + return url; + } + + private static final class UrlByteSource + extends ByteSource { + private final URL url; + + private UrlByteSource(URL url) { + this.url = Preconditions.checkNotNull(url); + } + + @Override + public InputStream openStream() throws IOException { + return this.url.openStream(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.url)); + return new StringBuilder(24 + string.length()).append("Resources.asByteSource(").append(string).append(")").toString(); + } + } +} diff --git a/src/com/google/common/io/package-info.java b/src/com/google/common/io/package-info.java new file mode 100644 index 0000000..99aa0be --- /dev/null +++ b/src/com/google/common/io/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.io; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/math/BigIntegerMath.java b/src/com/google/common/math/BigIntegerMath.java new file mode 100644 index 0000000..896c9e5 --- /dev/null +++ b/src/com/google/common/math/BigIntegerMath.java @@ -0,0 +1,277 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.DoubleMath; +import com.google.common.math.DoubleUtils; +import com.google.common.math.IntMath; +import com.google.common.math.LongMath; +import com.google.common.math.MathPreconditions; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; + +@GwtCompatible(emulated=true) +public final class BigIntegerMath { + @VisibleForTesting + static final int SQRT2_PRECOMPUTE_THRESHOLD = 256; + @VisibleForTesting + static final BigInteger SQRT2_PRECOMPUTED_BITS = new BigInteger("16a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a", 16); + private static final double LN_10 = Math.log(10.0); + private static final double LN_2 = Math.log(2.0); + + public static boolean isPowerOfTwo(BigInteger x) { + Preconditions.checkNotNull(x); + return x.signum() > 0 && x.getLowestSetBit() == x.bitLength() - 1; + } + + public static int log2(BigInteger x, RoundingMode mode) { + MathPreconditions.checkPositive("x", Preconditions.checkNotNull(x)); + int logFloor = x.bitLength() - 1; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(BigIntegerMath.isPowerOfTwo(x)); + } + case DOWN: + case FLOOR: { + return logFloor; + } + case UP: + case CEILING: { + return BigIntegerMath.isPowerOfTwo(x) ? logFloor : logFloor + 1; + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + if (logFloor < 256) { + BigInteger halfPower = SQRT2_PRECOMPUTED_BITS.shiftRight(256 - logFloor); + if (x.compareTo(halfPower) <= 0) { + return logFloor; + } + return logFloor + 1; + } + BigInteger x2 = x.pow(2); + int logX2Floor = x2.bitLength() - 1; + return logX2Floor < 2 * logFloor + 1 ? logFloor : logFloor + 1; + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="TODO") + public static int log10(BigInteger x, RoundingMode mode) { + MathPreconditions.checkPositive("x", x); + if (BigIntegerMath.fitsInLong(x)) { + return LongMath.log10(x.longValue(), mode); + } + int approxLog10 = (int)((double)BigIntegerMath.log2(x, RoundingMode.FLOOR) * LN_2 / LN_10); + BigInteger approxPow = BigInteger.TEN.pow(approxLog10); + int approxCmp = approxPow.compareTo(x); + if (approxCmp > 0) { + do { + --approxLog10; + } while ((approxCmp = (approxPow = approxPow.divide(BigInteger.TEN)).compareTo(x)) > 0); + } else { + BigInteger nextPow = BigInteger.TEN.multiply(approxPow); + int nextCmp = nextPow.compareTo(x); + while (nextCmp <= 0) { + ++approxLog10; + approxPow = nextPow; + approxCmp = nextCmp; + nextPow = BigInteger.TEN.multiply(approxPow); + nextCmp = nextPow.compareTo(x); + } + } + int floorLog = approxLog10; + BigInteger floorPow = approxPow; + int floorCmp = approxCmp; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(floorCmp == 0); + } + case DOWN: + case FLOOR: { + return floorLog; + } + case UP: + case CEILING: { + return floorPow.equals(x) ? floorLog : floorLog + 1; + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + BigInteger x2 = x.pow(2); + BigInteger halfPowerSquared = floorPow.pow(2).multiply(BigInteger.TEN); + return x2.compareTo(halfPowerSquared) <= 0 ? floorLog : floorLog + 1; + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="TODO") + public static BigInteger sqrt(BigInteger x, RoundingMode mode) { + MathPreconditions.checkNonNegative("x", x); + if (BigIntegerMath.fitsInLong(x)) { + return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode)); + } + BigInteger sqrtFloor = BigIntegerMath.sqrtFloor(x); + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x)); + } + case DOWN: + case FLOOR: { + return sqrtFloor; + } + case UP: + case CEILING: { + int sqrtFloorInt = sqrtFloor.intValue(); + boolean sqrtFloorIsExact = sqrtFloorInt * sqrtFloorInt == x.intValue() && sqrtFloor.pow(2).equals(x); + return sqrtFloorIsExact ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor); + return halfSquare.compareTo(x) >= 0 ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="TODO") + private static BigInteger sqrtFloor(BigInteger x) { + BigInteger sqrt0; + int log2 = BigIntegerMath.log2(x, RoundingMode.FLOOR); + if (log2 < 1023) { + sqrt0 = BigIntegerMath.sqrtApproxWithDoubles(x); + } else { + int shift = log2 - 52 & 0xFFFFFFFE; + sqrt0 = BigIntegerMath.sqrtApproxWithDoubles(x.shiftRight(shift)).shiftLeft(shift >> 1); + } + BigInteger sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1); + if (sqrt0.equals(sqrt1)) { + return sqrt0; + } + while ((sqrt1 = (sqrt0 = sqrt1).add(x.divide(sqrt0)).shiftRight(1)).compareTo(sqrt0) < 0) { + } + return sqrt0; + } + + @GwtIncompatible(value="TODO") + private static BigInteger sqrtApproxWithDoubles(BigInteger x) { + return DoubleMath.roundToBigInteger(Math.sqrt(DoubleUtils.bigToDouble(x)), RoundingMode.HALF_EVEN); + } + + @GwtIncompatible(value="TODO") + public static BigInteger divide(BigInteger p, BigInteger q, RoundingMode mode) { + BigDecimal pDec = new BigDecimal(p); + BigDecimal qDec = new BigDecimal(q); + return pDec.divide(qDec, 0, mode).toBigIntegerExact(); + } + + public static BigInteger factorial(int n) { + MathPreconditions.checkNonNegative("n", n); + if (n < LongMath.factorials.length) { + return BigInteger.valueOf(LongMath.factorials[n]); + } + int approxSize = IntMath.divide(n * IntMath.log2(n, RoundingMode.CEILING), 64, RoundingMode.CEILING); + ArrayList bignums = new ArrayList(approxSize); + int startingNumber = LongMath.factorials.length; + long product = LongMath.factorials[startingNumber - 1]; + int shift = Long.numberOfTrailingZeros(product); + int productBits = LongMath.log2(product >>= shift, RoundingMode.FLOOR) + 1; + int bits = LongMath.log2(startingNumber, RoundingMode.FLOOR) + 1; + int nextPowerOfTwo = 1 << bits - 1; + for (long num = (long)startingNumber; num <= (long)n; ++num) { + if ((num & (long)nextPowerOfTwo) != 0L) { + nextPowerOfTwo <<= 1; + ++bits; + } + int tz = Long.numberOfTrailingZeros(num); + long normalizedNum = num >> tz; + shift += tz; + int normalizedBits = bits - tz; + if (normalizedBits + productBits >= 64) { + bignums.add(BigInteger.valueOf(product)); + product = 1L; + productBits = 0; + } + productBits = LongMath.log2(product *= normalizedNum, RoundingMode.FLOOR) + 1; + } + if (product > 1L) { + bignums.add(BigInteger.valueOf(product)); + } + return BigIntegerMath.listProduct(bignums).shiftLeft(shift); + } + + static BigInteger listProduct(List nums) { + return BigIntegerMath.listProduct(nums, 0, nums.size()); + } + + static BigInteger listProduct(List nums, int start, int end) { + switch (end - start) { + case 0: { + return BigInteger.ONE; + } + case 1: { + return nums.get(start); + } + case 2: { + return nums.get(start).multiply(nums.get(start + 1)); + } + case 3: { + return nums.get(start).multiply(nums.get(start + 1)).multiply(nums.get(start + 2)); + } + } + int m = end + start >>> 1; + return BigIntegerMath.listProduct(nums, start, m).multiply(BigIntegerMath.listProduct(nums, m, end)); + } + + public static BigInteger binomial(int n, int k) { + int bits; + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", k, n); + if (k > n >> 1) { + k = n - k; + } + if (k < LongMath.biggestBinomials.length && n <= LongMath.biggestBinomials[k]) { + return BigInteger.valueOf(LongMath.binomial(n, k)); + } + BigInteger accum = BigInteger.ONE; + long numeratorAccum = n; + long denominatorAccum = 1L; + int numeratorBits = bits = LongMath.log2(n, RoundingMode.CEILING); + for (int i = 1; i < k; ++i) { + int p = n - i; + int q = i + 1; + if (numeratorBits + bits >= 63) { + accum = accum.multiply(BigInteger.valueOf(numeratorAccum)).divide(BigInteger.valueOf(denominatorAccum)); + numeratorAccum = p; + denominatorAccum = q; + numeratorBits = bits; + continue; + } + numeratorAccum *= (long)p; + denominatorAccum *= (long)q; + numeratorBits += bits; + } + return accum.multiply(BigInteger.valueOf(numeratorAccum)).divide(BigInteger.valueOf(denominatorAccum)); + } + + @GwtIncompatible(value="TODO") + static boolean fitsInLong(BigInteger x) { + return x.bitLength() <= 63; + } + + private BigIntegerMath() { + } +} diff --git a/src/com/google/common/math/DoubleMath.java b/src/com/google/common/math/DoubleMath.java new file mode 100644 index 0000000..7429718 --- /dev/null +++ b/src/com/google/common/math/DoubleMath.java @@ -0,0 +1,260 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.DoubleUtils; +import com.google.common.math.LongMath; +import com.google.common.math.MathPreconditions; +import com.google.common.primitives.Booleans; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.util.Iterator; + +@GwtCompatible(emulated=true) +public final class DoubleMath { + private static final double MIN_INT_AS_DOUBLE = -2.147483648E9; + private static final double MAX_INT_AS_DOUBLE = 2.147483647E9; + private static final double MIN_LONG_AS_DOUBLE = -9.223372036854776E18; + private static final double MAX_LONG_AS_DOUBLE_PLUS_ONE = 9.223372036854776E18; + private static final double LN_2 = Math.log(2.0); + @VisibleForTesting + static final int MAX_FACTORIAL = 170; + @VisibleForTesting + static final double[] everySixteenthFactorial = new double[]{1.0, 2.0922789888E13, 2.631308369336935E35, 1.2413915592536073E61, 1.2688693218588417E89, 7.156945704626381E118, 9.916779348709496E149, 1.974506857221074E182, 3.856204823625804E215, 5.5502938327393044E249, 4.7147236359920616E284}; + + @GwtIncompatible(value="#isMathematicalInteger, com.google.common.math.DoubleUtils") + static double roundIntermediate(double x, RoundingMode mode) { + if (!DoubleUtils.isFinite(x)) { + throw new ArithmeticException("input is infinite or NaN"); + } + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(DoubleMath.isMathematicalInteger(x)); + return x; + } + case FLOOR: { + if (x >= 0.0 || DoubleMath.isMathematicalInteger(x)) { + return x; + } + return x - 1.0; + } + case CEILING: { + if (x <= 0.0 || DoubleMath.isMathematicalInteger(x)) { + return x; + } + return x + 1.0; + } + case DOWN: { + return x; + } + case UP: { + if (DoubleMath.isMathematicalInteger(x)) { + return x; + } + return x + Math.copySign(1.0, x); + } + case HALF_EVEN: { + return Math.rint(x); + } + case HALF_UP: { + double z = Math.rint(x); + if (Math.abs(x - z) == 0.5) { + return x + Math.copySign(0.5, x); + } + return z; + } + case HALF_DOWN: { + double z = Math.rint(x); + if (Math.abs(x - z) == 0.5) { + return x; + } + return z; + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="#roundIntermediate") + public static int roundToInt(double x, RoundingMode mode) { + double z = DoubleMath.roundIntermediate(x, mode); + MathPreconditions.checkInRange(z > -2.147483649E9 & z < 2.147483648E9); + return (int)z; + } + + @GwtIncompatible(value="#roundIntermediate") + public static long roundToLong(double x, RoundingMode mode) { + double z = DoubleMath.roundIntermediate(x, mode); + MathPreconditions.checkInRange(-9.223372036854776E18 - z < 1.0 & z < 9.223372036854776E18); + return (long)z; + } + + @GwtIncompatible(value="#roundIntermediate, java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static BigInteger roundToBigInteger(double x, RoundingMode mode) { + if (-9.223372036854776E18 - (x = DoubleMath.roundIntermediate(x, mode)) < 1.0 & x < 9.223372036854776E18) { + return BigInteger.valueOf((long)x); + } + int exponent = Math.getExponent(x); + long significand = DoubleUtils.getSignificand(x); + BigInteger result = BigInteger.valueOf(significand).shiftLeft(exponent - 52); + return x < 0.0 ? result.negate() : result; + } + + @GwtIncompatible(value="com.google.common.math.DoubleUtils") + public static boolean isPowerOfTwo(double x) { + return x > 0.0 && DoubleUtils.isFinite(x) && LongMath.isPowerOfTwo(DoubleUtils.getSignificand(x)); + } + + public static double log2(double x) { + return Math.log(x) / LN_2; + } + + @GwtIncompatible(value="java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static int log2(double x, RoundingMode mode) { + boolean increment; + Preconditions.checkArgument(x > 0.0 && DoubleUtils.isFinite(x), "x must be positive and finite"); + int exponent = Math.getExponent(x); + if (!DoubleUtils.isNormal(x)) { + return DoubleMath.log2(x * 4.503599627370496E15, mode) - 52; + } + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(DoubleMath.isPowerOfTwo(x)); + } + case FLOOR: { + increment = false; + break; + } + case CEILING: { + increment = !DoubleMath.isPowerOfTwo(x); + break; + } + case DOWN: { + increment = exponent < 0 & !DoubleMath.isPowerOfTwo(x); + break; + } + case UP: { + increment = exponent >= 0 & !DoubleMath.isPowerOfTwo(x); + break; + } + case HALF_EVEN: + case HALF_UP: + case HALF_DOWN: { + double xScaled = DoubleUtils.scaleNormalize(x); + increment = xScaled * xScaled > 2.0; + break; + } + default: { + throw new AssertionError(); + } + } + return increment ? exponent + 1 : exponent; + } + + @GwtIncompatible(value="java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static boolean isMathematicalInteger(double x) { + return DoubleUtils.isFinite(x) && (x == 0.0 || 52 - Long.numberOfTrailingZeros(DoubleUtils.getSignificand(x)) <= Math.getExponent(x)); + } + + public static double factorial(int n) { + MathPreconditions.checkNonNegative("n", n); + if (n > 170) { + return Double.POSITIVE_INFINITY; + } + double accum = 1.0; + for (int i = 1 + (n & 0xFFFFFFF0); i <= n; ++i) { + accum *= (double)i; + } + return accum * everySixteenthFactorial[n >> 4]; + } + + public static boolean fuzzyEquals(double a, double b, double tolerance) { + MathPreconditions.checkNonNegative("tolerance", tolerance); + return Math.copySign(a - b, 1.0) <= tolerance || a == b || Double.isNaN(a) && Double.isNaN(b); + } + + public static int fuzzyCompare(double a, double b, double tolerance) { + if (DoubleMath.fuzzyEquals(a, b, tolerance)) { + return 0; + } + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return Booleans.compare(Double.isNaN(a), Double.isNaN(b)); + } + + @GwtIncompatible(value="MeanAccumulator") + public static double mean(double ... values) { + MeanAccumulator accumulator = new MeanAccumulator(); + for (double value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + @GwtIncompatible(value="MeanAccumulator") + public static double mean(int ... values) { + MeanAccumulator accumulator = new MeanAccumulator(); + for (int value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + @GwtIncompatible(value="MeanAccumulator") + public static double mean(long ... values) { + MeanAccumulator accumulator = new MeanAccumulator(); + for (long value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + @GwtIncompatible(value="MeanAccumulator") + public static double mean(Iterable values) { + MeanAccumulator accumulator = new MeanAccumulator(); + for (Number number : values) { + accumulator.add(number.doubleValue()); + } + return accumulator.mean(); + } + + @GwtIncompatible(value="MeanAccumulator") + public static double mean(Iterator values) { + MeanAccumulator accumulator = new MeanAccumulator(); + while (values.hasNext()) { + accumulator.add(values.next().doubleValue()); + } + return accumulator.mean(); + } + + private DoubleMath() { + } + + @GwtIncompatible(value="com.google.common.math.DoubleUtils") + private static final class MeanAccumulator { + private long count = 0L; + private double mean = 0.0; + + private MeanAccumulator() { + } + + void add(double value) { + Preconditions.checkArgument(DoubleUtils.isFinite(value)); + ++this.count; + this.mean += (value - this.mean) / (double)this.count; + } + + double mean() { + Preconditions.checkArgument(this.count > 0L, "Cannot take mean of 0 values"); + return this.mean; + } + } +} diff --git a/src/com/google/common/math/DoubleUtils.java b/src/com/google/common/math/DoubleUtils.java new file mode 100644 index 0000000..1d9fe58 --- /dev/null +++ b/src/com/google/common/math/DoubleUtils.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.base.Preconditions; +import java.math.BigInteger; + +final class DoubleUtils { + static final long SIGNIFICAND_MASK = 0xFFFFFFFFFFFFFL; + static final long EXPONENT_MASK = 0x7FF0000000000000L; + static final long SIGN_MASK = Long.MIN_VALUE; + static final int SIGNIFICAND_BITS = 52; + static final int EXPONENT_BIAS = 1023; + static final long IMPLICIT_BIT = 0x10000000000000L; + private static final long ONE_BITS = Double.doubleToRawLongBits(1.0); + + private DoubleUtils() { + } + + static double nextDown(double d) { + return -Math.nextUp(-d); + } + + static long getSignificand(double d) { + Preconditions.checkArgument(DoubleUtils.isFinite(d), "not a normal value"); + int exponent = Math.getExponent(d); + long bits = Double.doubleToRawLongBits(d); + return exponent == -1023 ? bits << 1 : (bits &= 0xFFFFFFFFFFFFFL) | 0x10000000000000L; + } + + static boolean isFinite(double d) { + return Math.getExponent(d) <= 1023; + } + + static boolean isNormal(double d) { + return Math.getExponent(d) >= -1022; + } + + static double scaleNormalize(double x) { + long significand = Double.doubleToRawLongBits(x) & 0xFFFFFFFFFFFFFL; + return Double.longBitsToDouble(significand | ONE_BITS); + } + + static double bigToDouble(BigInteger x) { + BigInteger absX = x.abs(); + int exponent = absX.bitLength() - 1; + if (exponent < 63) { + return x.longValue(); + } + if (exponent > 1023) { + return (double)x.signum() * Double.POSITIVE_INFINITY; + } + int shift = exponent - 52 - 1; + long twiceSignifFloor = absX.shiftRight(shift).longValue(); + long signifFloor = twiceSignifFloor >> 1; + boolean increment = (twiceSignifFloor & 1L) != 0L && (((signifFloor &= 0xFFFFFFFFFFFFFL) & 1L) != 0L || absX.getLowestSetBit() < shift); + long signifRounded = increment ? signifFloor + 1L : signifFloor; + long bits = (long)(exponent + 1023) << 52; + bits += signifRounded; + return Double.longBitsToDouble(bits |= (long)x.signum() & Long.MIN_VALUE); + } + + static double ensureNonNegative(double value) { + Preconditions.checkArgument(!Double.isNaN(value)); + if (value > 0.0) { + return value; + } + return 0.0; + } +} diff --git a/src/com/google/common/math/IntMath.java b/src/com/google/common/math/IntMath.java new file mode 100644 index 0000000..5de4228 --- /dev/null +++ b/src/com/google/common/math/IntMath.java @@ -0,0 +1,343 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.MathPreconditions; +import java.math.RoundingMode; + +@GwtCompatible(emulated=true) +public final class IntMath { + @VisibleForTesting + static final int MAX_POWER_OF_SQRT2_UNSIGNED = -1257966797; + @VisibleForTesting + static final byte[] maxLog10ForLeadingZeros = new byte[]{9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0}; + @VisibleForTesting + static final int[] powersOf10 = new int[]{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + @VisibleForTesting + static final int[] halfPowersOf10 = new int[]{3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766, Integer.MAX_VALUE}; + @VisibleForTesting + static final int FLOOR_SQRT_MAX_INT = 46340; + private static final int[] factorials = new int[]{1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600}; + @VisibleForTesting + static int[] biggestBinomials = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, 65536, 2345, 477, 193, 110, 75, 58, 49, 43, 39, 37, 35, 34, 34, 33}; + + public static boolean isPowerOfTwo(int x) { + return x > 0 & (x & x - 1) == 0; + } + + @VisibleForTesting + static int lessThanBranchFree(int x, int y) { + return ~(~(x - y)) >>> 31; + } + + public static int log2(int x, RoundingMode mode) { + MathPreconditions.checkPositive("x", x); + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(IntMath.isPowerOfTwo(x)); + } + case DOWN: + case FLOOR: { + return 31 - Integer.numberOfLeadingZeros(x); + } + case UP: + case CEILING: { + return 32 - Integer.numberOfLeadingZeros(x - 1); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + int leadingZeros = Integer.numberOfLeadingZeros(x); + int cmp = -1257966797 >>> leadingZeros; + int logFloor = 31 - leadingZeros; + return logFloor + IntMath.lessThanBranchFree(cmp, x); + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="need BigIntegerMath to adequately test") + public static int log10(int x, RoundingMode mode) { + MathPreconditions.checkPositive("x", x); + int logFloor = IntMath.log10Floor(x); + int floorPow = powersOf10[logFloor]; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(x == floorPow); + } + case DOWN: + case FLOOR: { + return logFloor; + } + case UP: + case CEILING: { + return logFloor + IntMath.lessThanBranchFree(floorPow, x); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + return logFloor + IntMath.lessThanBranchFree(halfPowersOf10[logFloor], x); + } + } + throw new AssertionError(); + } + + private static int log10Floor(int x) { + byte y = maxLog10ForLeadingZeros[Integer.numberOfLeadingZeros(x)]; + return y - IntMath.lessThanBranchFree(x, powersOf10[y]); + } + + @GwtIncompatible(value="failing tests") + public static int pow(int b, int k) { + MathPreconditions.checkNonNegative("exponent", k); + switch (b) { + case 0: { + return k == 0 ? 1 : 0; + } + case 1: { + return 1; + } + case -1: { + return (k & 1) == 0 ? 1 : -1; + } + case 2: { + return k < 32 ? 1 << k : 0; + } + case -2: { + if (k < 32) { + return (k & 1) == 0 ? 1 << k : -(1 << k); + } + return 0; + } + } + int accum = 1; + while (true) { + switch (k) { + case 0: { + return accum; + } + case 1: { + return b * accum; + } + } + accum *= (k & 1) == 0 ? 1 : b; + b *= b; + k >>= 1; + } + } + + @GwtIncompatible(value="need BigIntegerMath to adequately test") + public static int sqrt(int x, RoundingMode mode) { + MathPreconditions.checkNonNegative("x", x); + int sqrtFloor = IntMath.sqrtFloor(x); + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(sqrtFloor * sqrtFloor == x); + } + case DOWN: + case FLOOR: { + return sqrtFloor; + } + case UP: + case CEILING: { + return sqrtFloor + IntMath.lessThanBranchFree(sqrtFloor * sqrtFloor, x); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + int halfSquare = sqrtFloor * sqrtFloor + sqrtFloor; + return sqrtFloor + IntMath.lessThanBranchFree(halfSquare, x); + } + } + throw new AssertionError(); + } + + private static int sqrtFloor(int x) { + return (int)Math.sqrt(x); + } + + public static int divide(int p, int q, RoundingMode mode) { + boolean increment; + Preconditions.checkNotNull(mode); + if (q == 0) { + throw new ArithmeticException("/ by zero"); + } + int div = p / q; + int rem = p - q * div; + if (rem == 0) { + return div; + } + int signum = 1 | (p ^ q) >> 31; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(rem == 0); + } + case DOWN: { + increment = false; + break; + } + case UP: { + increment = true; + break; + } + case CEILING: { + increment = signum > 0; + break; + } + case FLOOR: { + increment = signum < 0; + break; + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + int absRem = Math.abs(rem); + int cmpRemToHalfDivisor = absRem - (Math.abs(q) - absRem); + if (cmpRemToHalfDivisor == 0) { + increment = mode == RoundingMode.HALF_UP || mode == RoundingMode.HALF_EVEN & (div & 1) != 0; + break; + } + increment = cmpRemToHalfDivisor > 0; + break; + } + default: { + throw new AssertionError(); + } + } + return increment ? div + signum : div; + } + + public static int mod(int x, int m) { + if (m <= 0) { + int n = m; + throw new ArithmeticException(new StringBuilder(31).append("Modulus ").append(n).append(" must be > 0").toString()); + } + int result = x % m; + return result >= 0 ? result : result + m; + } + + public static int gcd(int a, int b) { + MathPreconditions.checkNonNegative("a", a); + MathPreconditions.checkNonNegative("b", b); + if (a == 0) { + return b; + } + if (b == 0) { + return a; + } + int aTwos = Integer.numberOfTrailingZeros(a); + a >>= aTwos; + int bTwos = Integer.numberOfTrailingZeros(b); + b >>= bTwos; + while (a != b) { + int delta = a - b; + int minDeltaOrZero = delta & delta >> 31; + a = delta - minDeltaOrZero - minDeltaOrZero; + b += minDeltaOrZero; + a >>= Integer.numberOfTrailingZeros(a); + } + return a << Math.min(aTwos, bTwos); + } + + public static int checkedAdd(int a, int b) { + long result = (long)a + (long)b; + MathPreconditions.checkNoOverflow(result == (long)((int)result)); + return (int)result; + } + + public static int checkedSubtract(int a, int b) { + long result = (long)a - (long)b; + MathPreconditions.checkNoOverflow(result == (long)((int)result)); + return (int)result; + } + + public static int checkedMultiply(int a, int b) { + long result = (long)a * (long)b; + MathPreconditions.checkNoOverflow(result == (long)((int)result)); + return (int)result; + } + + public static int checkedPow(int b, int k) { + MathPreconditions.checkNonNegative("exponent", k); + switch (b) { + case 0: { + return k == 0 ? 1 : 0; + } + case 1: { + return 1; + } + case -1: { + return (k & 1) == 0 ? 1 : -1; + } + case 2: { + MathPreconditions.checkNoOverflow(k < 31); + return 1 << k; + } + case -2: { + MathPreconditions.checkNoOverflow(k < 32); + return (k & 1) == 0 ? 1 << k : -1 << k; + } + } + int accum = 1; + while (true) { + switch (k) { + case 0: { + return accum; + } + case 1: { + return IntMath.checkedMultiply(accum, b); + } + } + if ((k & 1) != 0) { + accum = IntMath.checkedMultiply(accum, b); + } + if ((k >>= 1) <= 0) continue; + MathPreconditions.checkNoOverflow(-46340 <= b & b <= 46340); + b *= b; + } + } + + public static int factorial(int n) { + MathPreconditions.checkNonNegative("n", n); + return n < factorials.length ? factorials[n] : Integer.MAX_VALUE; + } + + @GwtIncompatible(value="need BigIntegerMath to adequately test") + public static int binomial(int n, int k) { + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", k, n); + if (k > n >> 1) { + k = n - k; + } + if (k >= biggestBinomials.length || n > biggestBinomials[k]) { + return Integer.MAX_VALUE; + } + switch (k) { + case 0: { + return 1; + } + case 1: { + return n; + } + } + long result = 1L; + for (int i = 0; i < k; ++i) { + result *= (long)(n - i); + result /= (long)(i + 1); + } + return (int)result; + } + + public static int mean(int x, int y) { + return (x & y) + ((x ^ y) >> 1); + } + + private IntMath() { + } +} diff --git a/src/com/google/common/math/LongMath.java b/src/com/google/common/math/LongMath.java new file mode 100644 index 0000000..325d7bd --- /dev/null +++ b/src/com/google/common/math/LongMath.java @@ -0,0 +1,414 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import com.google.common.math.MathPreconditions; +import java.math.RoundingMode; + +@GwtCompatible(emulated=true) +public final class LongMath { + @VisibleForTesting + static final long MAX_POWER_OF_SQRT2_UNSIGNED = -5402926248376769404L; + @VisibleForTesting + static final byte[] maxLog10ForLeadingZeros = new byte[]{19, 18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0}; + @GwtIncompatible(value="TODO") + @VisibleForTesting + static final long[] powersOf10 = new long[]{1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L, 10000000000L, 100000000000L, 1000000000000L, 10000000000000L, 100000000000000L, 1000000000000000L, 10000000000000000L, 100000000000000000L, 1000000000000000000L}; + @GwtIncompatible(value="TODO") + @VisibleForTesting + static final long[] halfPowersOf10 = new long[]{3L, 31L, 316L, 3162L, 31622L, 316227L, 3162277L, 31622776L, 316227766L, 3162277660L, 31622776601L, 316227766016L, 3162277660168L, 31622776601683L, 316227766016837L, 3162277660168379L, 31622776601683793L, 316227766016837933L, 3162277660168379331L}; + @VisibleForTesting + static final long FLOOR_SQRT_MAX_LONG = 3037000499L; + static final long[] factorials = new long[]{1L, 1L, 2L, 6L, 24L, 120L, 720L, 5040L, 40320L, 362880L, 3628800L, 39916800L, 479001600L, 6227020800L, 87178291200L, 1307674368000L, 20922789888000L, 355687428096000L, 6402373705728000L, 121645100408832000L, 2432902008176640000L}; + static final int[] biggestBinomials = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 3810779, 121977, 16175, 4337, 1733, 887, 534, 361, 265, 206, 169, 143, 125, 111, 101, 94, 88, 83, 79, 76, 74, 72, 70, 69, 68, 67, 67, 66, 66, 66, 66}; + @VisibleForTesting + static final int[] biggestSimpleBinomials = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 2642246, 86251, 11724, 3218, 1313, 684, 419, 287, 214, 169, 139, 119, 105, 95, 87, 81, 76, 73, 70, 68, 66, 64, 63, 62, 62, 61, 61, 61}; + + public static boolean isPowerOfTwo(long x) { + return x > 0L & (x & x - 1L) == 0L; + } + + @VisibleForTesting + static int lessThanBranchFree(long x, long y) { + return (int)((x - y ^ 0xFFFFFFFFFFFFFFFFL ^ 0xFFFFFFFFFFFFFFFFL) >>> 63); + } + + public static int log2(long x, RoundingMode mode) { + MathPreconditions.checkPositive("x", x); + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(LongMath.isPowerOfTwo(x)); + } + case DOWN: + case FLOOR: { + return 63 - Long.numberOfLeadingZeros(x); + } + case UP: + case CEILING: { + return 64 - Long.numberOfLeadingZeros(x - 1L); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + int leadingZeros = Long.numberOfLeadingZeros(x); + long cmp = -5402926248376769404L >>> leadingZeros; + int logFloor = 63 - leadingZeros; + return logFloor + LongMath.lessThanBranchFree(cmp, x); + } + } + throw new AssertionError((Object)"impossible"); + } + + @GwtIncompatible(value="TODO") + public static int log10(long x, RoundingMode mode) { + MathPreconditions.checkPositive("x", x); + int logFloor = LongMath.log10Floor(x); + long floorPow = powersOf10[logFloor]; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(x == floorPow); + } + case DOWN: + case FLOOR: { + return logFloor; + } + case UP: + case CEILING: { + return logFloor + LongMath.lessThanBranchFree(floorPow, x); + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + return logFloor + LongMath.lessThanBranchFree(halfPowersOf10[logFloor], x); + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="TODO") + static int log10Floor(long x) { + byte y = maxLog10ForLeadingZeros[Long.numberOfLeadingZeros(x)]; + return y - LongMath.lessThanBranchFree(x, powersOf10[y]); + } + + @GwtIncompatible(value="TODO") + public static long pow(long b, int k) { + MathPreconditions.checkNonNegative("exponent", k); + if (-2L <= b && b <= 2L) { + switch ((int)b) { + case 0: { + return k == 0 ? 1L : 0L; + } + case 1: { + return 1L; + } + case -1: { + return (k & 1) == 0 ? 1L : -1L; + } + case 2: { + return k < 64 ? 1L << k : 0L; + } + case -2: { + if (k < 64) { + return (k & 1) == 0 ? 1L << k : -(1L << k); + } + return 0L; + } + } + throw new AssertionError(); + } + long accum = 1L; + while (true) { + switch (k) { + case 0: { + return accum; + } + case 1: { + return accum * b; + } + } + accum *= (k & 1) == 0 ? 1L : b; + b *= b; + k >>= 1; + } + } + + @GwtIncompatible(value="TODO") + public static long sqrt(long x, RoundingMode mode) { + MathPreconditions.checkNonNegative("x", x); + if (LongMath.fitsInInt(x)) { + return IntMath.sqrt((int)x, mode); + } + long guess = (long)Math.sqrt(x); + long guessSquared = guess * guess; + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(guessSquared == x); + return guess; + } + case DOWN: + case FLOOR: { + if (x < guessSquared) { + return guess - 1L; + } + return guess; + } + case UP: + case CEILING: { + if (x > guessSquared) { + return guess + 1L; + } + return guess; + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + long sqrtFloor = guess - (long)(x < guessSquared ? 1 : 0); + long halfSquare = sqrtFloor * sqrtFloor + sqrtFloor; + return sqrtFloor + (long)LongMath.lessThanBranchFree(halfSquare, x); + } + } + throw new AssertionError(); + } + + @GwtIncompatible(value="TODO") + public static long divide(long p, long q, RoundingMode mode) { + boolean increment; + Preconditions.checkNotNull(mode); + long div = p / q; + long rem = p - q * div; + if (rem == 0L) { + return div; + } + int signum = 1 | (int)((p ^ q) >> 63); + switch (mode) { + case UNNECESSARY: { + MathPreconditions.checkRoundingUnnecessary(rem == 0L); + } + case DOWN: { + increment = false; + break; + } + case UP: { + increment = true; + break; + } + case CEILING: { + increment = signum > 0; + break; + } + case FLOOR: { + increment = signum < 0; + break; + } + case HALF_DOWN: + case HALF_UP: + case HALF_EVEN: { + long absRem = Math.abs(rem); + long cmpRemToHalfDivisor = absRem - (Math.abs(q) - absRem); + if (cmpRemToHalfDivisor == 0L) { + increment = mode == RoundingMode.HALF_UP | mode == RoundingMode.HALF_EVEN & (div & 1L) != 0L; + break; + } + increment = cmpRemToHalfDivisor > 0L; + break; + } + default: { + throw new AssertionError(); + } + } + return increment ? div + (long)signum : div; + } + + @GwtIncompatible(value="TODO") + public static int mod(long x, int m) { + return (int)LongMath.mod(x, (long)m); + } + + @GwtIncompatible(value="TODO") + public static long mod(long x, long m) { + if (m <= 0L) { + throw new ArithmeticException("Modulus must be positive"); + } + long result = x % m; + return result >= 0L ? result : result + m; + } + + public static long gcd(long a, long b) { + MathPreconditions.checkNonNegative("a", a); + MathPreconditions.checkNonNegative("b", b); + if (a == 0L) { + return b; + } + if (b == 0L) { + return a; + } + int aTwos = Long.numberOfTrailingZeros(a); + a >>= aTwos; + int bTwos = Long.numberOfTrailingZeros(b); + b >>= bTwos; + while (a != b) { + long delta = a - b; + long minDeltaOrZero = delta & delta >> 63; + a = delta - minDeltaOrZero - minDeltaOrZero; + b += minDeltaOrZero; + a >>= Long.numberOfTrailingZeros(a); + } + return a << Math.min(aTwos, bTwos); + } + + @GwtIncompatible(value="TODO") + public static long checkedAdd(long a, long b) { + long result = a + b; + MathPreconditions.checkNoOverflow((a ^ b) < 0L | (a ^ result) >= 0L); + return result; + } + + @GwtIncompatible(value="TODO") + public static long checkedSubtract(long a, long b) { + long result = a - b; + MathPreconditions.checkNoOverflow((a ^ b) >= 0L | (a ^ result) >= 0L); + return result; + } + + @GwtIncompatible(value="TODO") + public static long checkedMultiply(long a, long b) { + int leadingZeros = Long.numberOfLeadingZeros(a) + Long.numberOfLeadingZeros(a ^ 0xFFFFFFFFFFFFFFFFL) + Long.numberOfLeadingZeros(b) + Long.numberOfLeadingZeros(b ^ 0xFFFFFFFFFFFFFFFFL); + if (leadingZeros > 65) { + return a * b; + } + MathPreconditions.checkNoOverflow(leadingZeros >= 64); + MathPreconditions.checkNoOverflow(a >= 0L | b != Long.MIN_VALUE); + long result = a * b; + MathPreconditions.checkNoOverflow(a == 0L || result / a == b); + return result; + } + + @GwtIncompatible(value="TODO") + public static long checkedPow(long b, int k) { + MathPreconditions.checkNonNegative("exponent", k); + if (b >= -2L & b <= 2L) { + switch ((int)b) { + case 0: { + return k == 0 ? 1L : 0L; + } + case 1: { + return 1L; + } + case -1: { + return (k & 1) == 0 ? 1L : -1L; + } + case 2: { + MathPreconditions.checkNoOverflow(k < 63); + return 1L << k; + } + case -2: { + MathPreconditions.checkNoOverflow(k < 64); + return (k & 1) == 0 ? 1L << k : -1L << k; + } + } + throw new AssertionError(); + } + long accum = 1L; + while (true) { + switch (k) { + case 0: { + return accum; + } + case 1: { + return LongMath.checkedMultiply(accum, b); + } + } + if ((k & 1) != 0) { + accum = LongMath.checkedMultiply(accum, b); + } + if ((k >>= 1) <= 0) continue; + MathPreconditions.checkNoOverflow(b <= 3037000499L); + b *= b; + } + } + + @GwtIncompatible(value="TODO") + public static long factorial(int n) { + MathPreconditions.checkNonNegative("n", n); + return n < factorials.length ? factorials[n] : Long.MAX_VALUE; + } + + public static long binomial(int n, int k) { + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", k, n); + if (k > n >> 1) { + k = n - k; + } + switch (k) { + case 0: { + return 1L; + } + case 1: { + return n; + } + } + if (n < factorials.length) { + return factorials[n] / (factorials[k] * factorials[n - k]); + } + if (k >= biggestBinomials.length || n > biggestBinomials[k]) { + return Long.MAX_VALUE; + } + if (k < biggestSimpleBinomials.length && n <= biggestSimpleBinomials[k]) { + long result = n--; + for (int i = 2; i <= k; ++i) { + result *= (long)n; + result /= (long)i; + --n; + } + return result; + } + int nBits = LongMath.log2(n, RoundingMode.CEILING); + long result = 1L; + long numerator = n--; + long denominator = 1L; + int numeratorBits = nBits; + int i = 2; + while (i <= k) { + if (numeratorBits + nBits < 63) { + numerator *= (long)n; + denominator *= (long)i; + numeratorBits += nBits; + } else { + result = LongMath.multiplyFraction(result, numerator, denominator); + numerator = n; + denominator = i; + numeratorBits = nBits; + } + ++i; + --n; + } + return LongMath.multiplyFraction(result, numerator, denominator); + } + + static long multiplyFraction(long x, long numerator, long denominator) { + if (x == 1L) { + return numerator / denominator; + } + long commonDivisor = LongMath.gcd(x, denominator); + return (x /= commonDivisor) * (numerator / (denominator /= commonDivisor)); + } + + static boolean fitsInInt(long x) { + return (long)((int)x) == x; + } + + public static long mean(long x, long y) { + return (x & y) + ((x ^ y) >> 1); + } + + private LongMath() { + } +} diff --git a/src/com/google/common/math/MathPreconditions.java b/src/com/google/common/math/MathPreconditions.java new file mode 100644 index 0000000..fd98314 --- /dev/null +++ b/src/com/google/common/math/MathPreconditions.java @@ -0,0 +1,95 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import java.math.BigInteger; +import javax.annotation.Nullable; + +@GwtCompatible +final class MathPreconditions { + static int checkPositive(@Nullable String role, int x) { + if (x <= 0) { + String string = String.valueOf(String.valueOf(role)); + int n = x; + throw new IllegalArgumentException(new StringBuilder(26 + string.length()).append(string).append(" (").append(n).append(") must be > 0").toString()); + } + return x; + } + + static long checkPositive(@Nullable String role, long x) { + if (x <= 0L) { + String string = String.valueOf(String.valueOf(role)); + long l = x; + throw new IllegalArgumentException(new StringBuilder(35 + string.length()).append(string).append(" (").append(l).append(") must be > 0").toString()); + } + return x; + } + + static BigInteger checkPositive(@Nullable String role, BigInteger x) { + if (x.signum() <= 0) { + String string = String.valueOf(String.valueOf(role)); + String string2 = String.valueOf(String.valueOf(x)); + throw new IllegalArgumentException(new StringBuilder(15 + string.length() + string2.length()).append(string).append(" (").append(string2).append(") must be > 0").toString()); + } + return x; + } + + static int checkNonNegative(@Nullable String role, int x) { + if (x < 0) { + String string = String.valueOf(String.valueOf(role)); + int n = x; + throw new IllegalArgumentException(new StringBuilder(27 + string.length()).append(string).append(" (").append(n).append(") must be >= 0").toString()); + } + return x; + } + + static long checkNonNegative(@Nullable String role, long x) { + if (x < 0L) { + String string = String.valueOf(String.valueOf(role)); + long l = x; + throw new IllegalArgumentException(new StringBuilder(36 + string.length()).append(string).append(" (").append(l).append(") must be >= 0").toString()); + } + return x; + } + + static BigInteger checkNonNegative(@Nullable String role, BigInteger x) { + if (x.signum() < 0) { + String string = String.valueOf(String.valueOf(role)); + String string2 = String.valueOf(String.valueOf(x)); + throw new IllegalArgumentException(new StringBuilder(16 + string.length() + string2.length()).append(string).append(" (").append(string2).append(") must be >= 0").toString()); + } + return x; + } + + static double checkNonNegative(@Nullable String role, double x) { + if (!(x >= 0.0)) { + String string = String.valueOf(String.valueOf(role)); + double d = x; + throw new IllegalArgumentException(new StringBuilder(40 + string.length()).append(string).append(" (").append(d).append(") must be >= 0").toString()); + } + return x; + } + + static void checkRoundingUnnecessary(boolean condition) { + if (!condition) { + throw new ArithmeticException("mode was UNNECESSARY, but rounding was necessary"); + } + } + + static void checkInRange(boolean condition) { + if (!condition) { + throw new ArithmeticException("not in range"); + } + } + + static void checkNoOverflow(boolean condition) { + if (!condition) { + throw new ArithmeticException("overflow"); + } + } + + private MathPreconditions() { + } +} diff --git a/src/com/google/common/math/package-info.java b/src/com/google/common/math/package-info.java new file mode 100644 index 0000000..f28b532 --- /dev/null +++ b/src/com/google/common/math/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.math; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/net/HostAndPort.java b/src/com/google/common/net/HostAndPort.java new file mode 100644 index 0000000..5f9b747 --- /dev/null +++ b/src/com/google/common/net/HostAndPort.java @@ -0,0 +1,158 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.io.Serializable; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@Beta +@Immutable +@GwtCompatible +public final class HostAndPort +implements Serializable { + private static final int NO_PORT = -1; + private final String host; + private final int port; + private final boolean hasBracketlessColons; + private static final long serialVersionUID = 0L; + + private HostAndPort(String host, int port, boolean hasBracketlessColons) { + this.host = host; + this.port = port; + this.hasBracketlessColons = hasBracketlessColons; + } + + public String getHostText() { + return this.host; + } + + public boolean hasPort() { + return this.port >= 0; + } + + public int getPort() { + Preconditions.checkState(this.hasPort()); + return this.port; + } + + public int getPortOrDefault(int defaultPort) { + return this.hasPort() ? this.port : defaultPort; + } + + public static HostAndPort fromParts(String host, int port) { + Preconditions.checkArgument(HostAndPort.isValidPort(port), "Port out of range: %s", port); + HostAndPort parsedHost = HostAndPort.fromString(host); + Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", host); + return new HostAndPort(parsedHost.host, port, parsedHost.hasBracketlessColons); + } + + public static HostAndPort fromHost(String host) { + HostAndPort parsedHost = HostAndPort.fromString(host); + Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", host); + return parsedHost; + } + + public static HostAndPort fromString(String hostPortString) { + String host; + Preconditions.checkNotNull(hostPortString); + String portString = null; + boolean hasBracketlessColons = false; + if (hostPortString.startsWith("[")) { + String[] hostAndPort = HostAndPort.getHostAndPortFromBracketedHost(hostPortString); + host = hostAndPort[0]; + portString = hostAndPort[1]; + } else { + int colonPos = hostPortString.indexOf(58); + if (colonPos >= 0 && hostPortString.indexOf(58, colonPos + 1) == -1) { + host = hostPortString.substring(0, colonPos); + portString = hostPortString.substring(colonPos + 1); + } else { + host = hostPortString; + hasBracketlessColons = colonPos >= 0; + } + } + int port = -1; + if (!Strings.isNullOrEmpty(portString)) { + Preconditions.checkArgument(!portString.startsWith("+"), "Unparseable port number: %s", hostPortString); + try { + port = Integer.parseInt(portString); + } + catch (NumberFormatException e) { + String string = String.valueOf(hostPortString); + throw new IllegalArgumentException(string.length() != 0 ? "Unparseable port number: ".concat(string) : new String("Unparseable port number: ")); + } + Preconditions.checkArgument(HostAndPort.isValidPort(port), "Port number out of range: %s", hostPortString); + } + return new HostAndPort(host, port, hasBracketlessColons); + } + + private static String[] getHostAndPortFromBracketedHost(String hostPortString) { + int colonIndex = 0; + int closeBracketIndex = 0; + Preconditions.checkArgument(hostPortString.charAt(0) == '[', "Bracketed host-port string must start with a bracket: %s", hostPortString); + colonIndex = hostPortString.indexOf(58); + closeBracketIndex = hostPortString.lastIndexOf(93); + Preconditions.checkArgument(colonIndex > -1 && closeBracketIndex > colonIndex, "Invalid bracketed host/port: %s", hostPortString); + String host = hostPortString.substring(1, closeBracketIndex); + if (closeBracketIndex + 1 == hostPortString.length()) { + return new String[]{host, ""}; + } + Preconditions.checkArgument(hostPortString.charAt(closeBracketIndex + 1) == ':', "Only a colon may follow a close bracket: %s", hostPortString); + for (int i = closeBracketIndex + 2; i < hostPortString.length(); ++i) { + Preconditions.checkArgument(Character.isDigit(hostPortString.charAt(i)), "Port must be numeric: %s", hostPortString); + } + return new String[]{host, hostPortString.substring(closeBracketIndex + 2)}; + } + + public HostAndPort withDefaultPort(int defaultPort) { + Preconditions.checkArgument(HostAndPort.isValidPort(defaultPort)); + if (this.hasPort() || this.port == defaultPort) { + return this; + } + return new HostAndPort(this.host, defaultPort, this.hasBracketlessColons); + } + + public HostAndPort requireBracketsForIPv6() { + Preconditions.checkArgument(!this.hasBracketlessColons, "Possible bracketless IPv6 literal: %s", this.host); + return this; + } + + public boolean equals(@Nullable Object other) { + if (this == other) { + return true; + } + if (other instanceof HostAndPort) { + HostAndPort that = (HostAndPort)other; + return Objects.equal(this.host, that.host) && this.port == that.port && this.hasBracketlessColons == that.hasBracketlessColons; + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.host, this.port, this.hasBracketlessColons); + } + + public String toString() { + StringBuilder builder = new StringBuilder(this.host.length() + 8); + if (this.host.indexOf(58) >= 0) { + builder.append('[').append(this.host).append(']'); + } else { + builder.append(this.host); + } + if (this.hasPort()) { + builder.append(':').append(this.port); + } + return builder.toString(); + } + + private static boolean isValidPort(int port) { + return port >= 0 && port <= 65535; + } +} diff --git a/src/com/google/common/net/HostSpecifier.java b/src/com/google/common/net/HostSpecifier.java new file mode 100644 index 0000000..7ca3e4b --- /dev/null +++ b/src/com/google/common/net/HostSpecifier.java @@ -0,0 +1,85 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.net.HostAndPort; +import com.google.common.net.InetAddresses; +import com.google.common.net.InternetDomainName; +import java.net.InetAddress; +import java.text.ParseException; +import javax.annotation.Nullable; + +@Beta +public final class HostSpecifier { + private final String canonicalForm; + + private HostSpecifier(String canonicalForm) { + this.canonicalForm = canonicalForm; + } + + public static HostSpecifier fromValid(String specifier) { + HostAndPort parsedHost = HostAndPort.fromString(specifier); + Preconditions.checkArgument(!parsedHost.hasPort()); + String host = parsedHost.getHostText(); + InetAddress addr = null; + try { + addr = InetAddresses.forString(host); + } + catch (IllegalArgumentException e) { + // empty catch block + } + if (addr != null) { + return new HostSpecifier(InetAddresses.toUriString(addr)); + } + InternetDomainName domain = InternetDomainName.from(host); + if (domain.hasPublicSuffix()) { + return new HostSpecifier(domain.toString()); + } + String string = String.valueOf(host); + throw new IllegalArgumentException(string.length() != 0 ? "Domain name does not have a recognized public suffix: ".concat(string) : new String("Domain name does not have a recognized public suffix: ")); + } + + public static HostSpecifier from(String specifier) throws ParseException { + try { + return HostSpecifier.fromValid(specifier); + } + catch (IllegalArgumentException e) { + String string = String.valueOf(specifier); + ParseException parseException = new ParseException(string.length() != 0 ? "Invalid host specifier: ".concat(string) : new String("Invalid host specifier: "), 0); + parseException.initCause(e); + throw parseException; + } + } + + public static boolean isValid(String specifier) { + try { + HostSpecifier.fromValid(specifier); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public boolean equals(@Nullable Object other) { + if (this == other) { + return true; + } + if (other instanceof HostSpecifier) { + HostSpecifier that = (HostSpecifier)other; + return this.canonicalForm.equals(that.canonicalForm); + } + return false; + } + + public int hashCode() { + return this.canonicalForm.hashCode(); + } + + public String toString() { + return this.canonicalForm; + } +} diff --git a/src/com/google/common/net/HttpHeaders.java b/src/com/google/common/net/HttpHeaders.java new file mode 100644 index 0000000..23d7c12 --- /dev/null +++ b/src/com/google/common/net/HttpHeaders.java @@ -0,0 +1,98 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public final class HttpHeaders { + public static final String CACHE_CONTROL = "Cache-Control"; + public static final String CONTENT_LENGTH = "Content-Length"; + public static final String CONTENT_TYPE = "Content-Type"; + public static final String DATE = "Date"; + public static final String PRAGMA = "Pragma"; + public static final String VIA = "Via"; + public static final String WARNING = "Warning"; + public static final String ACCEPT = "Accept"; + public static final String ACCEPT_CHARSET = "Accept-Charset"; + public static final String ACCEPT_ENCODING = "Accept-Encoding"; + public static final String ACCEPT_LANGUAGE = "Accept-Language"; + public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; + public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; + public static final String AUTHORIZATION = "Authorization"; + public static final String CONNECTION = "Connection"; + public static final String COOKIE = "Cookie"; + public static final String EXPECT = "Expect"; + public static final String FROM = "From"; + @Beta + public static final String FOLLOW_ONLY_WHEN_PRERENDER_SHOWN = "Follow-Only-When-Prerender-Shown"; + public static final String HOST = "Host"; + public static final String IF_MATCH = "If-Match"; + public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + public static final String IF_NONE_MATCH = "If-None-Match"; + public static final String IF_RANGE = "If-Range"; + public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; + public static final String LAST_EVENT_ID = "Last-Event-ID"; + public static final String MAX_FORWARDS = "Max-Forwards"; + public static final String ORIGIN = "Origin"; + public static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; + public static final String RANGE = "Range"; + public static final String REFERER = "Referer"; + public static final String TE = "TE"; + public static final String UPGRADE = "Upgrade"; + public static final String USER_AGENT = "User-Agent"; + public static final String ACCEPT_RANGES = "Accept-Ranges"; + public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; + public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; + public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; + public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; + public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; + public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; + public static final String AGE = "Age"; + public static final String ALLOW = "Allow"; + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + public static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String CONTENT_LANGUAGE = "Content-Language"; + public static final String CONTENT_LOCATION = "Content-Location"; + public static final String CONTENT_MD5 = "Content-MD5"; + public static final String CONTENT_RANGE = "Content-Range"; + public static final String CONTENT_SECURITY_POLICY = "Content-Security-Policy"; + public static final String CONTENT_SECURITY_POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"; + public static final String ETAG = "ETag"; + public static final String EXPIRES = "Expires"; + public static final String LAST_MODIFIED = "Last-Modified"; + public static final String LINK = "Link"; + public static final String LOCATION = "Location"; + public static final String P3P = "P3P"; + public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; + public static final String REFRESH = "Refresh"; + public static final String RETRY_AFTER = "Retry-After"; + public static final String SERVER = "Server"; + public static final String SET_COOKIE = "Set-Cookie"; + public static final String SET_COOKIE2 = "Set-Cookie2"; + public static final String STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security"; + public static final String TIMING_ALLOW_ORIGIN = "Timing-Allow-Origin"; + public static final String TRAILER = "Trailer"; + public static final String TRANSFER_ENCODING = "Transfer-Encoding"; + public static final String VARY = "Vary"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + public static final String DNT = "DNT"; + public static final String X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"; + public static final String X_DO_NOT_TRACK = "X-Do-Not-Track"; + public static final String X_FORWARDED_FOR = "X-Forwarded-For"; + public static final String X_FORWARDED_PROTO = "X-Forwarded-Proto"; + public static final String X_FRAME_OPTIONS = "X-Frame-Options"; + public static final String X_POWERED_BY = "X-Powered-By"; + @Beta + public static final String PUBLIC_KEY_PINS = "Public-Key-Pins"; + @Beta + public static final String PUBLIC_KEY_PINS_REPORT_ONLY = "Public-Key-Pins-Report-Only"; + public static final String X_REQUESTED_WITH = "X-Requested-With"; + public static final String X_USER_IP = "X-User-IP"; + public static final String X_XSS_PROTECTION = "X-XSS-Protection"; + + private HttpHeaders() { + } +} diff --git a/src/com/google/common/net/InetAddresses.java b/src/com/google/common/net/InetAddresses.java new file mode 100644 index 0000000..cf0ddbc --- /dev/null +++ b/src/com/google/common/net/InetAddresses.java @@ -0,0 +1,480 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.hash.Hashing; +import com.google.common.io.ByteStreams; +import com.google.common.primitives.Ints; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Nullable; + +@Beta +public final class InetAddresses { + private static final int IPV4_PART_COUNT = 4; + private static final int IPV6_PART_COUNT = 8; + private static final Inet4Address LOOPBACK4 = (Inet4Address)InetAddresses.forString("127.0.0.1"); + private static final Inet4Address ANY4 = (Inet4Address)InetAddresses.forString("0.0.0.0"); + + private InetAddresses() { + } + + private static Inet4Address getInet4Address(byte[] bytes) { + Preconditions.checkArgument(bytes.length == 4, "Byte array has invalid length for an IPv4 address: %s != 4.", bytes.length); + return (Inet4Address)InetAddresses.bytesToInetAddress(bytes); + } + + public static InetAddress forString(String ipString) { + byte[] addr = InetAddresses.ipStringToBytes(ipString); + if (addr == null) { + throw new IllegalArgumentException(String.format("'%s' is not an IP string literal.", ipString)); + } + return InetAddresses.bytesToInetAddress(addr); + } + + public static boolean isInetAddress(String ipString) { + return InetAddresses.ipStringToBytes(ipString) != null; + } + + private static byte[] ipStringToBytes(String ipString) { + boolean hasColon = false; + boolean hasDot = false; + for (int i = 0; i < ipString.length(); ++i) { + char c = ipString.charAt(i); + if (c == '.') { + hasDot = true; + continue; + } + if (c == ':') { + if (hasDot) { + return null; + } + hasColon = true; + continue; + } + if (Character.digit(c, 16) != -1) continue; + return null; + } + if (hasColon) { + if (hasDot && (ipString = InetAddresses.convertDottedQuadToHex(ipString)) == null) { + return null; + } + return InetAddresses.textToNumericFormatV6(ipString); + } + if (hasDot) { + return InetAddresses.textToNumericFormatV4(ipString); + } + return null; + } + + private static byte[] textToNumericFormatV4(String ipString) { + String[] address = ipString.split("\\.", 5); + if (address.length != 4) { + return null; + } + byte[] bytes = new byte[4]; + try { + for (int i = 0; i < bytes.length; ++i) { + bytes[i] = InetAddresses.parseOctet(address[i]); + } + } + catch (NumberFormatException ex) { + return null; + } + return bytes; + } + + private static byte[] textToNumericFormatV6(String ipString) { + int partsLo; + int partsHi; + String[] parts = ipString.split(":", 10); + if (parts.length < 3 || parts.length > 9) { + return null; + } + int skipIndex = -1; + for (int i = 1; i < parts.length - 1; ++i) { + if (parts[i].length() != 0) continue; + if (skipIndex >= 0) { + return null; + } + skipIndex = i; + } + if (skipIndex >= 0) { + partsHi = skipIndex; + partsLo = parts.length - skipIndex - 1; + if (parts[0].length() == 0 && --partsHi != 0) { + return null; + } + if (parts[parts.length - 1].length() == 0 && --partsLo != 0) { + return null; + } + } else { + partsHi = parts.length; + partsLo = 0; + } + int partsSkipped = 8 - (partsHi + partsLo); + if (!(skipIndex < 0 ? partsSkipped == 0 : partsSkipped >= 1)) { + return null; + } + ByteBuffer rawBytes = ByteBuffer.allocate(16); + try { + int i; + for (i = 0; i < partsHi; ++i) { + rawBytes.putShort(InetAddresses.parseHextet(parts[i])); + } + for (i = 0; i < partsSkipped; ++i) { + rawBytes.putShort((short)0); + } + for (i = partsLo; i > 0; --i) { + rawBytes.putShort(InetAddresses.parseHextet(parts[parts.length - i])); + } + } + catch (NumberFormatException ex) { + return null; + } + return rawBytes.array(); + } + + private static String convertDottedQuadToHex(String ipString) { + int lastColon = ipString.lastIndexOf(58); + String initialPart = ipString.substring(0, lastColon + 1); + String dottedQuad = ipString.substring(lastColon + 1); + byte[] quad = InetAddresses.textToNumericFormatV4(dottedQuad); + if (quad == null) { + return null; + } + String penultimate = Integer.toHexString((quad[0] & 0xFF) << 8 | quad[1] & 0xFF); + String ultimate = Integer.toHexString((quad[2] & 0xFF) << 8 | quad[3] & 0xFF); + String string = String.valueOf(String.valueOf(initialPart)); + String string2 = String.valueOf(String.valueOf(penultimate)); + String string3 = String.valueOf(String.valueOf(ultimate)); + return new StringBuilder(1 + string.length() + string2.length() + string3.length()).append(string).append(string2).append(":").append(string3).toString(); + } + + private static byte parseOctet(String ipPart) { + int octet = Integer.parseInt(ipPart); + if (octet > 255 || ipPart.startsWith("0") && ipPart.length() > 1) { + throw new NumberFormatException(); + } + return (byte)octet; + } + + private static short parseHextet(String ipPart) { + int hextet = Integer.parseInt(ipPart, 16); + if (hextet > 65535) { + throw new NumberFormatException(); + } + return (short)hextet; + } + + private static InetAddress bytesToInetAddress(byte[] addr) { + try { + return InetAddress.getByAddress(addr); + } + catch (UnknownHostException e) { + throw new AssertionError((Object)e); + } + } + + public static String toAddrString(InetAddress ip) { + Preconditions.checkNotNull(ip); + if (ip instanceof Inet4Address) { + return ip.getHostAddress(); + } + Preconditions.checkArgument(ip instanceof Inet6Address); + byte[] bytes = ip.getAddress(); + int[] hextets = new int[8]; + for (int i = 0; i < hextets.length; ++i) { + hextets[i] = Ints.fromBytes((byte)0, (byte)0, bytes[2 * i], bytes[2 * i + 1]); + } + InetAddresses.compressLongestRunOfZeroes(hextets); + return InetAddresses.hextetsToIPv6String(hextets); + } + + private static void compressLongestRunOfZeroes(int[] hextets) { + int bestRunStart = -1; + int bestRunLength = -1; + int runStart = -1; + for (int i = 0; i < hextets.length + 1; ++i) { + if (i < hextets.length && hextets[i] == 0) { + if (runStart >= 0) continue; + runStart = i; + continue; + } + if (runStart < 0) continue; + int runLength = i - runStart; + if (runLength > bestRunLength) { + bestRunStart = runStart; + bestRunLength = runLength; + } + runStart = -1; + } + if (bestRunLength >= 2) { + Arrays.fill(hextets, bestRunStart, bestRunStart + bestRunLength, -1); + } + } + + private static String hextetsToIPv6String(int[] hextets) { + StringBuilder buf = new StringBuilder(39); + boolean lastWasNumber = false; + for (int i = 0; i < hextets.length; ++i) { + boolean thisIsNumber; + boolean bl = thisIsNumber = hextets[i] >= 0; + if (thisIsNumber) { + if (lastWasNumber) { + buf.append(':'); + } + buf.append(Integer.toHexString(hextets[i])); + } else if (i == 0 || lastWasNumber) { + buf.append("::"); + } + lastWasNumber = thisIsNumber; + } + return buf.toString(); + } + + public static String toUriString(InetAddress ip) { + if (ip instanceof Inet6Address) { + String string = String.valueOf(String.valueOf(InetAddresses.toAddrString(ip))); + return new StringBuilder(2 + string.length()).append("[").append(string).append("]").toString(); + } + return InetAddresses.toAddrString(ip); + } + + public static InetAddress forUriString(String hostAddr) { + int expectBytes; + String ipString; + Preconditions.checkNotNull(hostAddr); + if (hostAddr.startsWith("[") && hostAddr.endsWith("]")) { + ipString = hostAddr.substring(1, hostAddr.length() - 1); + expectBytes = 16; + } else { + ipString = hostAddr; + expectBytes = 4; + } + byte[] addr = InetAddresses.ipStringToBytes(ipString); + if (addr == null || addr.length != expectBytes) { + throw new IllegalArgumentException(String.format("Not a valid URI IP literal: '%s'", hostAddr)); + } + return InetAddresses.bytesToInetAddress(addr); + } + + public static boolean isUriInetAddress(String ipString) { + try { + InetAddresses.forUriString(ipString); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + public static boolean isCompatIPv4Address(Inet6Address ip) { + if (!ip.isIPv4CompatibleAddress()) { + return false; + } + byte[] bytes = ip.getAddress(); + return bytes[12] != 0 || bytes[13] != 0 || bytes[14] != 0 || bytes[15] != 0 && bytes[15] != 1; + } + + public static Inet4Address getCompatIPv4Address(Inet6Address ip) { + Preconditions.checkArgument(InetAddresses.isCompatIPv4Address(ip), "Address '%s' is not IPv4-compatible.", InetAddresses.toAddrString(ip)); + return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16)); + } + + public static boolean is6to4Address(Inet6Address ip) { + byte[] bytes = ip.getAddress(); + return bytes[0] == 32 && bytes[1] == 2; + } + + public static Inet4Address get6to4IPv4Address(Inet6Address ip) { + Preconditions.checkArgument(InetAddresses.is6to4Address(ip), "Address '%s' is not a 6to4 address.", InetAddresses.toAddrString(ip)); + return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 2, 6)); + } + + public static boolean isTeredoAddress(Inet6Address ip) { + byte[] bytes = ip.getAddress(); + return bytes[0] == 32 && bytes[1] == 1 && bytes[2] == 0 && bytes[3] == 0; + } + + public static TeredoInfo getTeredoInfo(Inet6Address ip) { + Preconditions.checkArgument(InetAddresses.isTeredoAddress(ip), "Address '%s' is not a Teredo address.", InetAddresses.toAddrString(ip)); + byte[] bytes = ip.getAddress(); + Inet4Address server = InetAddresses.getInet4Address(Arrays.copyOfRange(bytes, 4, 8)); + int flags = ByteStreams.newDataInput(bytes, 8).readShort() & 0xFFFF; + int port = ~ByteStreams.newDataInput(bytes, 10).readShort() & 0xFFFF; + byte[] clientBytes = Arrays.copyOfRange(bytes, 12, 16); + for (int i = 0; i < clientBytes.length; ++i) { + clientBytes[i] = ~clientBytes[i]; + } + Inet4Address client = InetAddresses.getInet4Address(clientBytes); + return new TeredoInfo(server, client, port, flags); + } + + public static boolean isIsatapAddress(Inet6Address ip) { + if (InetAddresses.isTeredoAddress(ip)) { + return false; + } + byte[] bytes = ip.getAddress(); + if ((bytes[8] | 3) != 3) { + return false; + } + return bytes[9] == 0 && bytes[10] == 94 && bytes[11] == -2; + } + + public static Inet4Address getIsatapIPv4Address(Inet6Address ip) { + Preconditions.checkArgument(InetAddresses.isIsatapAddress(ip), "Address '%s' is not an ISATAP address.", InetAddresses.toAddrString(ip)); + return InetAddresses.getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16)); + } + + public static boolean hasEmbeddedIPv4ClientAddress(Inet6Address ip) { + return InetAddresses.isCompatIPv4Address(ip) || InetAddresses.is6to4Address(ip) || InetAddresses.isTeredoAddress(ip); + } + + public static Inet4Address getEmbeddedIPv4ClientAddress(Inet6Address ip) { + if (InetAddresses.isCompatIPv4Address(ip)) { + return InetAddresses.getCompatIPv4Address(ip); + } + if (InetAddresses.is6to4Address(ip)) { + return InetAddresses.get6to4IPv4Address(ip); + } + if (InetAddresses.isTeredoAddress(ip)) { + return InetAddresses.getTeredoInfo(ip).getClient(); + } + throw new IllegalArgumentException(String.format("'%s' has no embedded IPv4 address.", InetAddresses.toAddrString(ip))); + } + + public static boolean isMappedIPv4Address(String ipString) { + byte[] bytes = InetAddresses.ipStringToBytes(ipString); + if (bytes != null && bytes.length == 16) { + int i; + for (i = 0; i < 10; ++i) { + if (bytes[i] == 0) continue; + return false; + } + for (i = 10; i < 12; ++i) { + if (bytes[i] == -1) continue; + return false; + } + return true; + } + return false; + } + + public static Inet4Address getCoercedIPv4Address(InetAddress ip) { + if (ip instanceof Inet4Address) { + return (Inet4Address)ip; + } + byte[] bytes = ip.getAddress(); + boolean leadingBytesOfZero = true; + for (int i = 0; i < 15; ++i) { + if (bytes[i] == 0) continue; + leadingBytesOfZero = false; + break; + } + if (leadingBytesOfZero && bytes[15] == 1) { + return LOOPBACK4; + } + if (leadingBytesOfZero && bytes[15] == 0) { + return ANY4; + } + Inet6Address ip6 = (Inet6Address)ip; + long addressAsLong = 0L; + addressAsLong = InetAddresses.hasEmbeddedIPv4ClientAddress(ip6) ? (long)InetAddresses.getEmbeddedIPv4ClientAddress(ip6).hashCode() : ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong(); + int coercedHash = Hashing.murmur3_32().hashLong(addressAsLong).asInt(); + if ((coercedHash |= 0xE0000000) == -1) { + coercedHash = -2; + } + return InetAddresses.getInet4Address(Ints.toByteArray(coercedHash)); + } + + public static int coerceToInteger(InetAddress ip) { + return ByteStreams.newDataInput(InetAddresses.getCoercedIPv4Address(ip).getAddress()).readInt(); + } + + public static Inet4Address fromInteger(int address) { + return InetAddresses.getInet4Address(Ints.toByteArray(address)); + } + + public static InetAddress fromLittleEndianByteArray(byte[] addr) throws UnknownHostException { + byte[] reversed = new byte[addr.length]; + for (int i = 0; i < addr.length; ++i) { + reversed[i] = addr[addr.length - i - 1]; + } + return InetAddress.getByAddress(reversed); + } + + public static InetAddress decrement(InetAddress address) { + int i; + byte[] addr = address.getAddress(); + for (i = addr.length - 1; i >= 0 && addr[i] == 0; --i) { + addr[i] = -1; + } + Preconditions.checkArgument(i >= 0, "Decrementing %s would wrap.", address); + int n = i; + addr[n] = (byte)(addr[n] - 1); + return InetAddresses.bytesToInetAddress(addr); + } + + public static InetAddress increment(InetAddress address) { + int i; + byte[] addr = address.getAddress(); + for (i = addr.length - 1; i >= 0 && addr[i] == -1; --i) { + addr[i] = 0; + } + Preconditions.checkArgument(i >= 0, "Incrementing %s would wrap.", address); + int n = i; + addr[n] = (byte)(addr[n] + 1); + return InetAddresses.bytesToInetAddress(addr); + } + + public static boolean isMaximum(InetAddress address) { + byte[] addr = address.getAddress(); + for (int i = 0; i < addr.length; ++i) { + if (addr[i] == -1) continue; + return false; + } + return true; + } + + @Beta + public static final class TeredoInfo { + private final Inet4Address server; + private final Inet4Address client; + private final int port; + private final int flags; + + public TeredoInfo(@Nullable Inet4Address server, @Nullable Inet4Address client, int port, int flags) { + Preconditions.checkArgument(port >= 0 && port <= 65535, "port '%s' is out of range (0 <= port <= 0xffff)", port); + Preconditions.checkArgument(flags >= 0 && flags <= 65535, "flags '%s' is out of range (0 <= flags <= 0xffff)", flags); + this.server = MoreObjects.firstNonNull(server, ANY4); + this.client = MoreObjects.firstNonNull(client, ANY4); + this.port = port; + this.flags = flags; + } + + public Inet4Address getServer() { + return this.server; + } + + public Inet4Address getClient() { + return this.client; + } + + public int getPort() { + return this.port; + } + + public int getFlags() { + return this.flags; + } + } +} diff --git a/src/com/google/common/net/InternetDomainName.java b/src/com/google/common/net/InternetDomainName.java new file mode 100644 index 0000000..1f8cd28 --- /dev/null +++ b/src/com/google/common/net/InternetDomainName.java @@ -0,0 +1,179 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; +import java.util.List; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public final class InternetDomainName { + private static final CharMatcher DOTS_MATCHER = CharMatcher.anyOf(".\u3002\uff0e\uff61"); + private static final Splitter DOT_SPLITTER = Splitter.on('.'); + private static final Joiner DOT_JOINER = Joiner.on('.'); + private static final int NO_PUBLIC_SUFFIX_FOUND = -1; + private static final String DOT_REGEX = "\\."; + private static final int MAX_PARTS = 127; + private static final int MAX_LENGTH = 253; + private static final int MAX_DOMAIN_PART_LENGTH = 63; + private final String name; + private final ImmutableList parts; + private final int publicSuffixIndex; + private static final CharMatcher DASH_MATCHER = CharMatcher.anyOf("-_"); + private static final CharMatcher PART_CHAR_MATCHER = CharMatcher.JAVA_LETTER_OR_DIGIT.or(DASH_MATCHER); + + InternetDomainName(String name) { + name = Ascii.toLowerCase(DOTS_MATCHER.replaceFrom((CharSequence)name, '.')); + if (name.endsWith(".")) { + name = name.substring(0, name.length() - 1); + } + Preconditions.checkArgument(name.length() <= 253, "Domain name too long: '%s':", name); + this.name = name; + this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); + Preconditions.checkArgument(this.parts.size() <= 127, "Domain has too many parts: '%s'", name); + Preconditions.checkArgument(InternetDomainName.validateSyntax(this.parts), "Not a valid domain name: '%s'", name); + this.publicSuffixIndex = this.findPublicSuffix(); + } + + private int findPublicSuffix() { + int partsSize = this.parts.size(); + for (int i = 0; i < partsSize; ++i) { + String ancestorName = DOT_JOINER.join(this.parts.subList(i, partsSize)); + if (PublicSuffixPatterns.EXACT.containsKey(ancestorName)) { + return i; + } + if (PublicSuffixPatterns.EXCLUDED.containsKey(ancestorName)) { + return i + 1; + } + if (!InternetDomainName.matchesWildcardPublicSuffix(ancestorName)) continue; + return i; + } + return -1; + } + + public static InternetDomainName from(String domain) { + return new InternetDomainName(Preconditions.checkNotNull(domain)); + } + + private static boolean validateSyntax(List parts) { + int lastIndex = parts.size() - 1; + if (!InternetDomainName.validatePart(parts.get(lastIndex), true)) { + return false; + } + for (int i = 0; i < lastIndex; ++i) { + String part = parts.get(i); + if (InternetDomainName.validatePart(part, false)) continue; + return false; + } + return true; + } + + private static boolean validatePart(String part, boolean isFinalPart) { + if (part.length() < 1 || part.length() > 63) { + return false; + } + String asciiChars = CharMatcher.ASCII.retainFrom(part); + if (!PART_CHAR_MATCHER.matchesAllOf(asciiChars)) { + return false; + } + if (DASH_MATCHER.matches(part.charAt(0)) || DASH_MATCHER.matches(part.charAt(part.length() - 1))) { + return false; + } + return !isFinalPart || !CharMatcher.DIGIT.matches(part.charAt(0)); + } + + public ImmutableList parts() { + return this.parts; + } + + public boolean isPublicSuffix() { + return this.publicSuffixIndex == 0; + } + + public boolean hasPublicSuffix() { + return this.publicSuffixIndex != -1; + } + + public InternetDomainName publicSuffix() { + return this.hasPublicSuffix() ? this.ancestor(this.publicSuffixIndex) : null; + } + + public boolean isUnderPublicSuffix() { + return this.publicSuffixIndex > 0; + } + + public boolean isTopPrivateDomain() { + return this.publicSuffixIndex == 1; + } + + public InternetDomainName topPrivateDomain() { + if (this.isTopPrivateDomain()) { + return this; + } + Preconditions.checkState(this.isUnderPublicSuffix(), "Not under a public suffix: %s", this.name); + return this.ancestor(this.publicSuffixIndex - 1); + } + + public boolean hasParent() { + return this.parts.size() > 1; + } + + public InternetDomainName parent() { + Preconditions.checkState(this.hasParent(), "Domain '%s' has no parent", this.name); + return this.ancestor(1); + } + + private InternetDomainName ancestor(int levels) { + return InternetDomainName.from(DOT_JOINER.join(this.parts.subList(levels, this.parts.size()))); + } + + public InternetDomainName child(String leftParts) { + String string = String.valueOf(String.valueOf(Preconditions.checkNotNull(leftParts))); + String string2 = String.valueOf(String.valueOf(this.name)); + return InternetDomainName.from(new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString()); + } + + public static boolean isValid(String name) { + try { + InternetDomainName.from(name); + return true; + } + catch (IllegalArgumentException e) { + return false; + } + } + + private static boolean matchesWildcardPublicSuffix(String domain) { + String[] pieces = domain.split(DOT_REGEX, 2); + return pieces.length == 2 && PublicSuffixPatterns.UNDER.containsKey(pieces[1]); + } + + public String toString() { + return this.name; + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (object instanceof InternetDomainName) { + InternetDomainName that = (InternetDomainName)object; + return this.name.equals(that.name); + } + return false; + } + + public int hashCode() { + return this.name.hashCode(); + } +} diff --git a/src/com/google/common/net/MediaType.java b/src/com/google/common/net/MediaType.java new file mode 100644 index 0000000..d010234 --- /dev/null +++ b/src/com/google/common/net/MediaType.java @@ -0,0 +1,398 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import java.nio.charset.Charset; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Map; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@Beta +@GwtCompatible +@Immutable +public final class MediaType { + private static final String CHARSET_ATTRIBUTE = "charset"; + private static final ImmutableListMultimap UTF_8_CONSTANT_PARAMETERS = ImmutableListMultimap.of("charset", Ascii.toLowerCase(Charsets.UTF_8.name())); + private static final CharMatcher TOKEN_MATCHER = CharMatcher.ASCII.and(CharMatcher.JAVA_ISO_CONTROL.negate()).and(CharMatcher.isNot(' ')).and(CharMatcher.noneOf("()<>@,;:\\\"/[]?=")); + private static final CharMatcher QUOTED_TEXT_MATCHER = CharMatcher.ASCII.and(CharMatcher.noneOf("\"\\\r")); + private static final CharMatcher LINEAR_WHITE_SPACE = CharMatcher.anyOf(" \t\r\n"); + private static final String APPLICATION_TYPE = "application"; + private static final String AUDIO_TYPE = "audio"; + private static final String IMAGE_TYPE = "image"; + private static final String TEXT_TYPE = "text"; + private static final String VIDEO_TYPE = "video"; + private static final String WILDCARD = "*"; + private static final Map KNOWN_TYPES = Maps.newHashMap(); + public static final MediaType ANY_TYPE = MediaType.createConstant("*", "*"); + public static final MediaType ANY_TEXT_TYPE = MediaType.createConstant("text", "*"); + public static final MediaType ANY_IMAGE_TYPE = MediaType.createConstant("image", "*"); + public static final MediaType ANY_AUDIO_TYPE = MediaType.createConstant("audio", "*"); + public static final MediaType ANY_VIDEO_TYPE = MediaType.createConstant("video", "*"); + public static final MediaType ANY_APPLICATION_TYPE = MediaType.createConstant("application", "*"); + public static final MediaType CACHE_MANIFEST_UTF_8 = MediaType.createConstantUtf8("text", "cache-manifest"); + public static final MediaType CSS_UTF_8 = MediaType.createConstantUtf8("text", "css"); + public static final MediaType CSV_UTF_8 = MediaType.createConstantUtf8("text", "csv"); + public static final MediaType HTML_UTF_8 = MediaType.createConstantUtf8("text", "html"); + public static final MediaType I_CALENDAR_UTF_8 = MediaType.createConstantUtf8("text", "calendar"); + public static final MediaType PLAIN_TEXT_UTF_8 = MediaType.createConstantUtf8("text", "plain"); + public static final MediaType TEXT_JAVASCRIPT_UTF_8 = MediaType.createConstantUtf8("text", "javascript"); + public static final MediaType TSV_UTF_8 = MediaType.createConstantUtf8("text", "tab-separated-values"); + public static final MediaType VCARD_UTF_8 = MediaType.createConstantUtf8("text", "vcard"); + public static final MediaType WML_UTF_8 = MediaType.createConstantUtf8("text", "vnd.wap.wml"); + public static final MediaType XML_UTF_8 = MediaType.createConstantUtf8("text", "xml"); + public static final MediaType BMP = MediaType.createConstant("image", "bmp"); + public static final MediaType CRW = MediaType.createConstant("image", "x-canon-crw"); + public static final MediaType GIF = MediaType.createConstant("image", "gif"); + public static final MediaType ICO = MediaType.createConstant("image", "vnd.microsoft.icon"); + public static final MediaType JPEG = MediaType.createConstant("image", "jpeg"); + public static final MediaType PNG = MediaType.createConstant("image", "png"); + public static final MediaType PSD = MediaType.createConstant("image", "vnd.adobe.photoshop"); + public static final MediaType SVG_UTF_8 = MediaType.createConstantUtf8("image", "svg+xml"); + public static final MediaType TIFF = MediaType.createConstant("image", "tiff"); + public static final MediaType WEBP = MediaType.createConstant("image", "webp"); + public static final MediaType MP4_AUDIO = MediaType.createConstant("audio", "mp4"); + public static final MediaType MPEG_AUDIO = MediaType.createConstant("audio", "mpeg"); + public static final MediaType OGG_AUDIO = MediaType.createConstant("audio", "ogg"); + public static final MediaType WEBM_AUDIO = MediaType.createConstant("audio", "webm"); + public static final MediaType MP4_VIDEO = MediaType.createConstant("video", "mp4"); + public static final MediaType MPEG_VIDEO = MediaType.createConstant("video", "mpeg"); + public static final MediaType OGG_VIDEO = MediaType.createConstant("video", "ogg"); + public static final MediaType QUICKTIME = MediaType.createConstant("video", "quicktime"); + public static final MediaType WEBM_VIDEO = MediaType.createConstant("video", "webm"); + public static final MediaType WMV = MediaType.createConstant("video", "x-ms-wmv"); + public static final MediaType APPLICATION_XML_UTF_8 = MediaType.createConstantUtf8("application", "xml"); + public static final MediaType ATOM_UTF_8 = MediaType.createConstantUtf8("application", "atom+xml"); + public static final MediaType BZIP2 = MediaType.createConstant("application", "x-bzip2"); + public static final MediaType EOT = MediaType.createConstant("application", "vnd.ms-fontobject"); + public static final MediaType EPUB = MediaType.createConstant("application", "epub+zip"); + public static final MediaType FORM_DATA = MediaType.createConstant("application", "x-www-form-urlencoded"); + public static final MediaType KEY_ARCHIVE = MediaType.createConstant("application", "pkcs12"); + public static final MediaType APPLICATION_BINARY = MediaType.createConstant("application", "binary"); + public static final MediaType GZIP = MediaType.createConstant("application", "x-gzip"); + public static final MediaType JAVASCRIPT_UTF_8 = MediaType.createConstantUtf8("application", "javascript"); + public static final MediaType JSON_UTF_8 = MediaType.createConstantUtf8("application", "json"); + public static final MediaType KML = MediaType.createConstant("application", "vnd.google-earth.kml+xml"); + public static final MediaType KMZ = MediaType.createConstant("application", "vnd.google-earth.kmz"); + public static final MediaType MBOX = MediaType.createConstant("application", "mbox"); + public static final MediaType APPLE_MOBILE_CONFIG = MediaType.createConstant("application", "x-apple-aspen-config"); + public static final MediaType MICROSOFT_EXCEL = MediaType.createConstant("application", "vnd.ms-excel"); + public static final MediaType MICROSOFT_POWERPOINT = MediaType.createConstant("application", "vnd.ms-powerpoint"); + public static final MediaType MICROSOFT_WORD = MediaType.createConstant("application", "msword"); + public static final MediaType OCTET_STREAM = MediaType.createConstant("application", "octet-stream"); + public static final MediaType OGG_CONTAINER = MediaType.createConstant("application", "ogg"); + public static final MediaType OOXML_DOCUMENT = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.wordprocessingml.document"); + public static final MediaType OOXML_PRESENTATION = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.presentationml.presentation"); + public static final MediaType OOXML_SHEET = MediaType.createConstant("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + public static final MediaType OPENDOCUMENT_GRAPHICS = MediaType.createConstant("application", "vnd.oasis.opendocument.graphics"); + public static final MediaType OPENDOCUMENT_PRESENTATION = MediaType.createConstant("application", "vnd.oasis.opendocument.presentation"); + public static final MediaType OPENDOCUMENT_SPREADSHEET = MediaType.createConstant("application", "vnd.oasis.opendocument.spreadsheet"); + public static final MediaType OPENDOCUMENT_TEXT = MediaType.createConstant("application", "vnd.oasis.opendocument.text"); + public static final MediaType PDF = MediaType.createConstant("application", "pdf"); + public static final MediaType POSTSCRIPT = MediaType.createConstant("application", "postscript"); + public static final MediaType PROTOBUF = MediaType.createConstant("application", "protobuf"); + public static final MediaType RDF_XML_UTF_8 = MediaType.createConstantUtf8("application", "rdf+xml"); + public static final MediaType RTF_UTF_8 = MediaType.createConstantUtf8("application", "rtf"); + public static final MediaType SFNT = MediaType.createConstant("application", "font-sfnt"); + public static final MediaType SHOCKWAVE_FLASH = MediaType.createConstant("application", "x-shockwave-flash"); + public static final MediaType SKETCHUP = MediaType.createConstant("application", "vnd.sketchup.skp"); + public static final MediaType TAR = MediaType.createConstant("application", "x-tar"); + public static final MediaType WOFF = MediaType.createConstant("application", "font-woff"); + public static final MediaType XHTML_UTF_8 = MediaType.createConstantUtf8("application", "xhtml+xml"); + public static final MediaType XRD_UTF_8 = MediaType.createConstantUtf8("application", "xrd+xml"); + public static final MediaType ZIP = MediaType.createConstant("application", "zip"); + private final String type; + private final String subtype; + private final ImmutableListMultimap parameters; + private static final Joiner.MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("="); + + private static MediaType createConstant(String type, String subtype) { + return MediaType.addKnownType(new MediaType(type, subtype, ImmutableListMultimap.of())); + } + + private static MediaType createConstantUtf8(String type, String subtype) { + return MediaType.addKnownType(new MediaType(type, subtype, UTF_8_CONSTANT_PARAMETERS)); + } + + private static MediaType addKnownType(MediaType mediaType) { + KNOWN_TYPES.put(mediaType, mediaType); + return mediaType; + } + + private MediaType(String type, String subtype, ImmutableListMultimap parameters) { + this.type = type; + this.subtype = subtype; + this.parameters = parameters; + } + + public String type() { + return this.type; + } + + public String subtype() { + return this.subtype; + } + + public ImmutableListMultimap parameters() { + return this.parameters; + } + + private Map> parametersAsMap() { + return Maps.transformValues(this.parameters.asMap(), new Function, ImmutableMultiset>(){ + + @Override + public ImmutableMultiset apply(Collection input) { + return ImmutableMultiset.copyOf(input); + } + }); + } + + public Optional charset() { + ImmutableSet charsetValues = ImmutableSet.copyOf(this.parameters.get((Object)CHARSET_ATTRIBUTE)); + switch (charsetValues.size()) { + case 0: { + return Optional.absent(); + } + case 1: { + return Optional.of(Charset.forName((String)Iterables.getOnlyElement(charsetValues))); + } + } + String string = String.valueOf(String.valueOf(charsetValues)); + throw new IllegalStateException(new StringBuilder(33 + string.length()).append("Multiple charset values defined: ").append(string).toString()); + } + + public MediaType withoutParameters() { + return this.parameters.isEmpty() ? this : MediaType.create(this.type, this.subtype); + } + + public MediaType withParameters(Multimap parameters) { + return MediaType.create(this.type, this.subtype, parameters); + } + + public MediaType withParameter(String attribute, String value) { + Preconditions.checkNotNull(attribute); + Preconditions.checkNotNull(value); + String normalizedAttribute = MediaType.normalizeToken(attribute); + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + for (Map.Entry entry : this.parameters.entries()) { + String key = (String)entry.getKey(); + if (normalizedAttribute.equals(key)) continue; + builder.put(key, entry.getValue()); + } + builder.put(normalizedAttribute, MediaType.normalizeParameterValue(normalizedAttribute, value)); + MediaType mediaType = new MediaType(this.type, this.subtype, (ImmutableListMultimap)builder.build()); + return MoreObjects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType); + } + + public MediaType withCharset(Charset charset) { + Preconditions.checkNotNull(charset); + return this.withParameter(CHARSET_ATTRIBUTE, charset.name()); + } + + public boolean hasWildcard() { + return WILDCARD.equals(this.type) || WILDCARD.equals(this.subtype); + } + + public boolean is(MediaType mediaTypeRange) { + return !(!mediaTypeRange.type.equals(WILDCARD) && !mediaTypeRange.type.equals(this.type) || !mediaTypeRange.subtype.equals(WILDCARD) && !mediaTypeRange.subtype.equals(this.subtype) || !((AbstractCollection)this.parameters.entries()).containsAll(mediaTypeRange.parameters.entries())); + } + + public static MediaType create(String type, String subtype) { + return MediaType.create(type, subtype, ImmutableListMultimap.of()); + } + + static MediaType createApplicationType(String subtype) { + return MediaType.create(APPLICATION_TYPE, subtype); + } + + static MediaType createAudioType(String subtype) { + return MediaType.create(AUDIO_TYPE, subtype); + } + + static MediaType createImageType(String subtype) { + return MediaType.create(IMAGE_TYPE, subtype); + } + + static MediaType createTextType(String subtype) { + return MediaType.create(TEXT_TYPE, subtype); + } + + static MediaType createVideoType(String subtype) { + return MediaType.create(VIDEO_TYPE, subtype); + } + + private static MediaType create(String type, String subtype, Multimap parameters) { + Preconditions.checkNotNull(type); + Preconditions.checkNotNull(subtype); + Preconditions.checkNotNull(parameters); + String normalizedType = MediaType.normalizeToken(type); + String normalizedSubtype = MediaType.normalizeToken(subtype); + Preconditions.checkArgument(!WILDCARD.equals(normalizedType) || WILDCARD.equals(normalizedSubtype), "A wildcard type cannot be used with a non-wildcard subtype"); + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + for (Map.Entry entry : parameters.entries()) { + String attribute = MediaType.normalizeToken(entry.getKey()); + builder.put(attribute, MediaType.normalizeParameterValue(attribute, entry.getValue())); + } + MediaType mediaType = new MediaType(normalizedType, normalizedSubtype, (ImmutableListMultimap)builder.build()); + return MoreObjects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType); + } + + private static String normalizeToken(String token) { + Preconditions.checkArgument(TOKEN_MATCHER.matchesAllOf(token)); + return Ascii.toLowerCase(token); + } + + private static String normalizeParameterValue(String attribute, String value) { + return CHARSET_ATTRIBUTE.equals(attribute) ? Ascii.toLowerCase(value) : value; + } + + public static MediaType parse(String input) { + Preconditions.checkNotNull(input); + Tokenizer tokenizer = new Tokenizer(input); + try { + String type = tokenizer.consumeToken(TOKEN_MATCHER); + tokenizer.consumeCharacter('/'); + String subtype = tokenizer.consumeToken(TOKEN_MATCHER); + ImmutableListMultimap.Builder parameters = ImmutableListMultimap.builder(); + while (tokenizer.hasMore()) { + String value; + tokenizer.consumeCharacter(';'); + tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); + String attribute = tokenizer.consumeToken(TOKEN_MATCHER); + tokenizer.consumeCharacter('='); + if ('\"' == tokenizer.previewChar()) { + tokenizer.consumeCharacter('\"'); + StringBuilder valueBuilder = new StringBuilder(); + while ('\"' != tokenizer.previewChar()) { + if ('\\' == tokenizer.previewChar()) { + tokenizer.consumeCharacter('\\'); + valueBuilder.append(tokenizer.consumeCharacter(CharMatcher.ASCII)); + continue; + } + valueBuilder.append(tokenizer.consumeToken(QUOTED_TEXT_MATCHER)); + } + value = valueBuilder.toString(); + tokenizer.consumeCharacter('\"'); + } else { + value = tokenizer.consumeToken(TOKEN_MATCHER); + } + parameters.put(attribute, value); + } + return MediaType.create(type, subtype, parameters.build()); + } + catch (IllegalStateException e) { + String string = String.valueOf(String.valueOf(input)); + throw new IllegalArgumentException(new StringBuilder(18 + string.length()).append("Could not parse '").append(string).append("'").toString(), e); + } + } + + public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof MediaType) { + MediaType that = (MediaType)obj; + return this.type.equals(that.type) && this.subtype.equals(that.subtype) && this.parametersAsMap().equals(that.parametersAsMap()); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(this.type, this.subtype, this.parametersAsMap()); + } + + public String toString() { + StringBuilder builder = new StringBuilder().append(this.type).append('/').append(this.subtype); + if (!this.parameters.isEmpty()) { + builder.append("; "); + ListMultimap quotedParameters = Multimaps.transformValues(this.parameters, new Function(){ + + @Override + public String apply(String value) { + return TOKEN_MATCHER.matchesAllOf(value) ? value : MediaType.escapeAndQuote(value); + } + }); + PARAMETER_JOINER.appendTo(builder, (Iterable>)quotedParameters.entries()); + } + return builder.toString(); + } + + private static String escapeAndQuote(String value) { + StringBuilder escaped = new StringBuilder(value.length() + 16).append('\"'); + for (char ch : value.toCharArray()) { + if (ch == '\r' || ch == '\\' || ch == '\"') { + escaped.append('\\'); + } + escaped.append(ch); + } + return escaped.append('\"').toString(); + } + + private static final class Tokenizer { + final String input; + int position = 0; + + Tokenizer(String input) { + this.input = input; + } + + String consumeTokenIfPresent(CharMatcher matcher) { + Preconditions.checkState(this.hasMore()); + int startPosition = this.position; + this.position = matcher.negate().indexIn(this.input, startPosition); + return this.hasMore() ? this.input.substring(startPosition, this.position) : this.input.substring(startPosition); + } + + String consumeToken(CharMatcher matcher) { + int startPosition = this.position; + String token = this.consumeTokenIfPresent(matcher); + Preconditions.checkState(this.position != startPosition); + return token; + } + + char consumeCharacter(CharMatcher matcher) { + Preconditions.checkState(this.hasMore()); + char c = this.previewChar(); + Preconditions.checkState(matcher.matches(c)); + ++this.position; + return c; + } + + char consumeCharacter(char c) { + Preconditions.checkState(this.hasMore()); + Preconditions.checkState(this.previewChar() == c); + ++this.position; + return c; + } + + char previewChar() { + Preconditions.checkState(this.hasMore()); + return this.input.charAt(this.position); + } + + boolean hasMore() { + return this.position >= 0 && this.position < this.input.length(); + } + } +} diff --git a/src/com/google/common/net/PercentEscaper.java b/src/com/google/common/net/PercentEscaper.java new file mode 100644 index 0000000..8cbb3df --- /dev/null +++ b/src/com/google/common/net/PercentEscaper.java @@ -0,0 +1,125 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.UnicodeEscaper; + +@Beta +@GwtCompatible +public final class PercentEscaper +extends UnicodeEscaper { + private static final char[] PLUS_SIGN = new char[]{'+'}; + private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + private final boolean plusForSpace; + private final boolean[] safeOctets; + + public PercentEscaper(String safeChars, boolean plusForSpace) { + Preconditions.checkNotNull(safeChars); + if (safeChars.matches(".*[0-9A-Za-z].*")) { + throw new IllegalArgumentException("Alphanumeric characters are always 'safe' and should not be explicitly specified"); + } + safeChars = String.valueOf(safeChars).concat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + if (plusForSpace && safeChars.contains(" ")) { + throw new IllegalArgumentException("plusForSpace cannot be specified when space is a 'safe' character"); + } + this.plusForSpace = plusForSpace; + this.safeOctets = PercentEscaper.createSafeOctets(safeChars); + } + + private static boolean[] createSafeOctets(String safeChars) { + char[] safeCharArray; + int maxChar = -1; + for (char c : safeCharArray = safeChars.toCharArray()) { + maxChar = Math.max(c, maxChar); + } + boolean[] octets = new boolean[maxChar + 1]; + for (char c : safeCharArray) { + octets[c] = true; + } + return octets; + } + + @Override + protected int nextEscapeIndex(CharSequence csq, int index, int end) { + char c; + Preconditions.checkNotNull(csq); + while (index < end && (c = csq.charAt(index)) < this.safeOctets.length && this.safeOctets[c]) { + ++index; + } + return index; + } + + @Override + public String escape(String s) { + Preconditions.checkNotNull(s); + int slen = s.length(); + for (int index = 0; index < slen; ++index) { + char c = s.charAt(index); + if (c < this.safeOctets.length && this.safeOctets[c]) continue; + return this.escapeSlow(s, index); + } + return s; + } + + @Override + protected char[] escape(int cp) { + if (cp < this.safeOctets.length && this.safeOctets[cp]) { + return null; + } + if (cp == 32 && this.plusForSpace) { + return PLUS_SIGN; + } + if (cp <= 127) { + char[] dest = new char[3]; + dest[0] = 37; + dest[2] = UPPER_HEX_DIGITS[cp & 0xF]; + dest[1] = UPPER_HEX_DIGITS[cp >>> 4]; + return dest; + } + if (cp <= 2047) { + char[] dest = new char[6]; + dest[0] = 37; + dest[3] = 37; + dest[5] = UPPER_HEX_DIGITS[cp & 0xF]; + dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[2] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF]; + dest[1] = UPPER_HEX_DIGITS[0xC | (cp >>>= 4)]; + return dest; + } + if (cp <= 65535) { + char[] dest = new char[9]; + dest[0] = 37; + dest[1] = 69; + dest[3] = 37; + dest[6] = 37; + dest[8] = UPPER_HEX_DIGITS[cp & 0xF]; + dest[7] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[5] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF]; + dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[2] = UPPER_HEX_DIGITS[cp >>>= 2]; + return dest; + } + if (cp <= 0x10FFFF) { + char[] dest = new char[12]; + dest[0] = 37; + dest[1] = 70; + dest[3] = 37; + dest[6] = 37; + dest[9] = 37; + dest[11] = UPPER_HEX_DIGITS[cp & 0xF]; + dest[10] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[8] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF]; + dest[7] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[5] = UPPER_HEX_DIGITS[(cp >>>= 2) & 0xF]; + dest[4] = UPPER_HEX_DIGITS[8 | (cp >>>= 4) & 3]; + dest[2] = UPPER_HEX_DIGITS[(cp >>>= 2) & 7]; + return dest; + } + int n = cp; + throw new IllegalArgumentException(new StringBuilder(43).append("Invalid unicode character value ").append(n).toString()); + } +} diff --git a/src/com/google/common/net/UrlEscapers.java b/src/com/google/common/net/UrlEscapers.java new file mode 100644 index 0000000..20dddb4 --- /dev/null +++ b/src/com/google/common/net/UrlEscapers.java @@ -0,0 +1,34 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; +import com.google.common.net.PercentEscaper; + +@Beta +@GwtCompatible +public final class UrlEscapers { + static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*"; + static final String URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS = "-._~!$'()*,;&=@:"; + private static final Escaper URL_FORM_PARAMETER_ESCAPER = new PercentEscaper("-_.*", true); + private static final Escaper URL_PATH_SEGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+", false); + private static final Escaper URL_FRAGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+/?", false); + + private UrlEscapers() { + } + + public static Escaper urlFormParameterEscaper() { + return URL_FORM_PARAMETER_ESCAPER; + } + + public static Escaper urlPathSegmentEscaper() { + return URL_PATH_SEGMENT_ESCAPER; + } + + public static Escaper urlFragmentEscaper() { + return URL_FRAGMENT_ESCAPER; + } +} diff --git a/src/com/google/common/net/package-info.java b/src/com/google/common/net/package-info.java new file mode 100644 index 0000000..d8c4ceb --- /dev/null +++ b/src/com/google/common/net/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.net; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/primitives/Booleans.java b/src/com/google/common/primitives/Booleans.java new file mode 100644 index 0000000..22e8277 --- /dev/null +++ b/src/com/google/common/primitives/Booleans.java @@ -0,0 +1,290 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + +@GwtCompatible +public final class Booleans { + private Booleans() { + } + + public static int hashCode(boolean value) { + return value ? 1231 : 1237; + } + + public static int compare(boolean a, boolean b) { + return a == b ? 0 : (a ? 1 : -1); + } + + public static boolean contains(boolean[] array, boolean target) { + for (boolean value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(boolean[] array, boolean target) { + return Booleans.indexOf(array, target, 0, array.length); + } + + private static int indexOf(boolean[] array, boolean target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(boolean[] array, boolean[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(boolean[] array, boolean target) { + return Booleans.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(boolean[] array, boolean target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static boolean[] concat(boolean[] ... arrays) { + int length = 0; + for (boolean[] array : arrays) { + length += array.length; + } + boolean[] result = new boolean[length]; + int pos = 0; + for (boolean[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Booleans.copyOf(array, minLength + padding) : array; + } + + private static boolean[] copyOf(boolean[] original, int length) { + boolean[] copy = new boolean[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, boolean ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 7); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static boolean[] toArray(Collection collection) { + if (collection instanceof BooleanArrayAsList) { + return ((BooleanArrayAsList)collection).toBooleanArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + boolean[] array = new boolean[len]; + for (int i = 0; i < len; ++i) { + array[i] = (Boolean)Preconditions.checkNotNull(boxedArray[i]); + } + return array; + } + + public static List asList(boolean ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new BooleanArrayAsList(backingArray); + } + + @Beta + public static int countTrue(boolean ... values) { + int count = 0; + for (boolean value : values) { + if (!value) continue; + ++count; + } + return count; + } + + @GwtCompatible + private static class BooleanArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final boolean[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + BooleanArrayAsList(boolean[] array) { + this(array, 0, array.length); + } + + BooleanArrayAsList(boolean[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Boolean get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Boolean && Booleans.indexOf(this.array, (Boolean)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Boolean && (i = Booleans.indexOf(this.array, (Boolean)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Boolean && (i = Booleans.lastIndexOf(this.array, (Boolean)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Boolean set(int index, Boolean element) { + Preconditions.checkElementIndex(index, this.size()); + boolean oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new BooleanArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof BooleanArrayAsList) { + BooleanArrayAsList that = (BooleanArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Booleans.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 7); + builder.append(this.array[this.start] ? "[true" : "[false"); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(this.array[i] ? ", true" : ", false"); + } + return builder.append(']').toString(); + } + + boolean[] toBooleanArray() { + int size = this.size(); + boolean[] result = new boolean[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(boolean[] left, boolean[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Booleans.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } +} diff --git a/src/com/google/common/primitives/Bytes.java b/src/com/google/common/primitives/Bytes.java new file mode 100644 index 0000000..1654f28 --- /dev/null +++ b/src/com/google/common/primitives/Bytes.java @@ -0,0 +1,240 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.RandomAccess; + +@GwtCompatible +public final class Bytes { + private Bytes() { + } + + public static int hashCode(byte value) { + return value; + } + + public static boolean contains(byte[] array, byte target) { + for (byte value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(byte[] array, byte target) { + return Bytes.indexOf(array, target, 0, array.length); + } + + private static int indexOf(byte[] array, byte target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(byte[] array, byte[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(byte[] array, byte target) { + return Bytes.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(byte[] array, byte target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static byte[] concat(byte[] ... arrays) { + int length = 0; + for (byte[] array : arrays) { + length += array.length; + } + byte[] result = new byte[length]; + int pos = 0; + for (byte[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + public static byte[] ensureCapacity(byte[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Bytes.copyOf(array, minLength + padding) : array; + } + + private static byte[] copyOf(byte[] original, int length) { + byte[] copy = new byte[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static byte[] toArray(Collection collection) { + if (collection instanceof ByteArrayAsList) { + return ((ByteArrayAsList)collection).toByteArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + byte[] array = new byte[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).byteValue(); + } + return array; + } + + public static List asList(byte ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new ByteArrayAsList(backingArray); + } + + @GwtCompatible + private static class ByteArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final byte[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + ByteArrayAsList(byte[] array) { + this(array, 0, array.length); + } + + ByteArrayAsList(byte[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Byte get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Byte && Bytes.indexOf(this.array, (Byte)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Byte && (i = Bytes.indexOf(this.array, (Byte)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Byte && (i = Bytes.lastIndexOf(this.array, (Byte)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Byte set(int index, Byte element) { + Preconditions.checkElementIndex(index, this.size()); + byte oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new ByteArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof ByteArrayAsList) { + ByteArrayAsList that = (ByteArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Bytes.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 5); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + byte[] toByteArray() { + int size = this.size(); + byte[] result = new byte[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } +} diff --git a/src/com/google/common/primitives/Chars.java b/src/com/google/common/primitives/Chars.java new file mode 100644 index 0000000..538c072 --- /dev/null +++ b/src/com/google/common/primitives/Chars.java @@ -0,0 +1,338 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + +@GwtCompatible(emulated=true) +public final class Chars { + public static final int BYTES = 2; + + private Chars() { + } + + public static int hashCode(char value) { + return value; + } + + public static char checkedCast(long value) { + char result = (char)value; + if ((long)result != value) { + long l = value; + throw new IllegalArgumentException(new StringBuilder(34).append("Out of range: ").append(l).toString()); + } + return result; + } + + public static char saturatedCast(long value) { + if (value > 65535L) { + return '\uffff'; + } + if (value < 0L) { + return '\u0000'; + } + return (char)value; + } + + public static int compare(char a, char b) { + return a - b; + } + + public static boolean contains(char[] array, char target) { + for (char value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(char[] array, char target) { + return Chars.indexOf(array, target, 0, array.length); + } + + private static int indexOf(char[] array, char target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(char[] array, char[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(char[] array, char target) { + return Chars.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(char[] array, char target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static char min(char ... array) { + Preconditions.checkArgument(array.length > 0); + char min = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] >= min) continue; + min = array[i]; + } + return min; + } + + public static char max(char ... array) { + Preconditions.checkArgument(array.length > 0); + char max = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] <= max) continue; + max = array[i]; + } + return max; + } + + public static char[] concat(char[] ... arrays) { + int length = 0; + for (char[] array : arrays) { + length += array.length; + } + char[] result = new char[length]; + int pos = 0; + for (char[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + @GwtIncompatible(value="doesn't work") + public static byte[] toByteArray(char value) { + return new byte[]{(byte)(value >> 8), (byte)value}; + } + + @GwtIncompatible(value="doesn't work") + public static char fromByteArray(byte[] bytes) { + Preconditions.checkArgument(bytes.length >= 2, "array too small: %s < %s", bytes.length, 2); + return Chars.fromBytes(bytes[0], bytes[1]); + } + + @GwtIncompatible(value="doesn't work") + public static char fromBytes(byte b1, byte b2) { + return (char)(b1 << 8 | b2 & 0xFF); + } + + public static char[] ensureCapacity(char[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Chars.copyOf(array, minLength + padding) : array; + } + + private static char[] copyOf(char[] original, int length) { + char[] copy = new char[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, char ... array) { + Preconditions.checkNotNull(separator); + int len = array.length; + if (len == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1)); + builder.append(array[0]); + for (int i = 1; i < len; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static char[] toArray(Collection collection) { + if (collection instanceof CharArrayAsList) { + return ((CharArrayAsList)collection).toCharArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + char[] array = new char[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Character)Preconditions.checkNotNull(boxedArray[i])).charValue(); + } + return array; + } + + public static List asList(char ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new CharArrayAsList(backingArray); + } + + @GwtCompatible + private static class CharArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final char[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + CharArrayAsList(char[] array) { + this(array, 0, array.length); + } + + CharArrayAsList(char[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Character get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return Character.valueOf(this.array[this.start + index]); + } + + @Override + public boolean contains(Object target) { + return target instanceof Character && Chars.indexOf(this.array, ((Character)target).charValue(), this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Character && (i = Chars.indexOf(this.array, ((Character)target).charValue(), this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Character && (i = Chars.lastIndexOf(this.array, ((Character)target).charValue(), this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Character set(int index, Character element) { + Preconditions.checkElementIndex(index, this.size()); + char oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element).charValue(); + return Character.valueOf(oldValue); + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new CharArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof CharArrayAsList) { + CharArrayAsList that = (CharArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Chars.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 3); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + char[] toCharArray() { + int size = this.size(); + char[] result = new char[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(char[] left, char[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Chars.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } +} diff --git a/src/com/google/common/primitives/Doubles.java b/src/com/google/common/primitives/Doubles.java new file mode 100644 index 0000000..78e5809 --- /dev/null +++ b/src/com/google/common/primitives/Doubles.java @@ -0,0 +1,371 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Doubles { + public static final int BYTES = 8; + @GwtIncompatible(value="regular expressions") + static final Pattern FLOATING_POINT_PATTERN = Doubles.fpPattern(); + + private Doubles() { + } + + public static int hashCode(double value) { + return Double.valueOf(value).hashCode(); + } + + public static int compare(double a, double b) { + return Double.compare(a, b); + } + + public static boolean isFinite(double value) { + return Double.NEGATIVE_INFINITY < value & value < Double.POSITIVE_INFINITY; + } + + public static boolean contains(double[] array, double target) { + for (double value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(double[] array, double target) { + return Doubles.indexOf(array, target, 0, array.length); + } + + private static int indexOf(double[] array, double target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(double[] array, double[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(double[] array, double target) { + return Doubles.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(double[] array, double target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static double min(double ... array) { + Preconditions.checkArgument(array.length > 0); + double min = array[0]; + for (int i = 1; i < array.length; ++i) { + min = Math.min(min, array[i]); + } + return min; + } + + public static double max(double ... array) { + Preconditions.checkArgument(array.length > 0); + double max = array[0]; + for (int i = 1; i < array.length; ++i) { + max = Math.max(max, array[i]); + } + return max; + } + + public static double[] concat(double[] ... arrays) { + int length = 0; + for (double[] array : arrays) { + length += array.length; + } + double[] result = new double[length]; + int pos = 0; + for (double[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + @Beta + public static Converter stringConverter() { + return DoubleConverter.INSTANCE; + } + + public static double[] ensureCapacity(double[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Doubles.copyOf(array, minLength + padding) : array; + } + + private static double[] copyOf(double[] original, int length) { + double[] copy = new double[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, double ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 12); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static double[] toArray(Collection collection) { + if (collection instanceof DoubleArrayAsList) { + return ((DoubleArrayAsList)collection).toDoubleArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + double[] array = new double[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).doubleValue(); + } + return array; + } + + public static List asList(double ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new DoubleArrayAsList(backingArray); + } + + @GwtIncompatible(value="regular expressions") + private static Pattern fpPattern() { + String decimal = "(?:\\d++(?:\\.\\d*+)?|\\.\\d++)"; + String completeDec = String.valueOf(decimal).concat("(?:[eE][+-]?\\d++)?[fFdD]?"); + String hex = "(?:\\p{XDigit}++(?:\\.\\p{XDigit}*+)?|\\.\\p{XDigit}++)"; + String string = String.valueOf(String.valueOf(hex)); + String completeHex = new StringBuilder(25 + string.length()).append("0[xX]").append(string).append("[pP][+-]?\\d++[fFdD]?").toString(); + String string2 = String.valueOf(String.valueOf(completeDec)); + String string3 = String.valueOf(String.valueOf(completeHex)); + String fpPattern = new StringBuilder(23 + string2.length() + string3.length()).append("[+-]?(?:NaN|Infinity|").append(string2).append("|").append(string3).append(")").toString(); + return Pattern.compile(fpPattern); + } + + @Nullable + @GwtIncompatible(value="regular expressions") + @Beta + public static Double tryParse(String string) { + if (FLOATING_POINT_PATTERN.matcher(string).matches()) { + try { + return Double.parseDouble(string); + } + catch (NumberFormatException numberFormatException) { + // empty catch block + } + } + return null; + } + + @GwtCompatible + private static class DoubleArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final double[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + DoubleArrayAsList(double[] array) { + this(array, 0, array.length); + } + + DoubleArrayAsList(double[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Double get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Double && Doubles.indexOf(this.array, (Double)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Double && (i = Doubles.indexOf(this.array, (Double)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Double && (i = Doubles.lastIndexOf(this.array, (Double)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Double set(int index, Double element) { + Preconditions.checkElementIndex(index, this.size()); + double oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new DoubleArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof DoubleArrayAsList) { + DoubleArrayAsList that = (DoubleArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Doubles.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 12); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + double[] toDoubleArray() { + int size = this.size(); + double[] result = new double[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(double[] left, double[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Double.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + private static final class DoubleConverter + extends Converter + implements Serializable { + static final DoubleConverter INSTANCE = new DoubleConverter(); + private static final long serialVersionUID = 1L; + + private DoubleConverter() { + } + + @Override + protected Double doForward(String value) { + return Double.valueOf(value); + } + + @Override + protected String doBackward(Double value) { + return value.toString(); + } + + public String toString() { + return "Doubles.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/primitives/Floats.java b/src/com/google/common/primitives/Floats.java new file mode 100644 index 0000000..07e95f8 --- /dev/null +++ b/src/com/google/common/primitives/Floats.java @@ -0,0 +1,356 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class Floats { + public static final int BYTES = 4; + + private Floats() { + } + + public static int hashCode(float value) { + return Float.valueOf(value).hashCode(); + } + + public static int compare(float a, float b) { + return Float.compare(a, b); + } + + public static boolean isFinite(float value) { + return Float.NEGATIVE_INFINITY < value & value < Float.POSITIVE_INFINITY; + } + + public static boolean contains(float[] array, float target) { + for (float value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(float[] array, float target) { + return Floats.indexOf(array, target, 0, array.length); + } + + private static int indexOf(float[] array, float target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(float[] array, float[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(float[] array, float target) { + return Floats.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(float[] array, float target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static float min(float ... array) { + Preconditions.checkArgument(array.length > 0); + float min = array[0]; + for (int i = 1; i < array.length; ++i) { + min = Math.min(min, array[i]); + } + return min; + } + + public static float max(float ... array) { + Preconditions.checkArgument(array.length > 0); + float max = array[0]; + for (int i = 1; i < array.length; ++i) { + max = Math.max(max, array[i]); + } + return max; + } + + public static float[] concat(float[] ... arrays) { + int length = 0; + for (float[] array : arrays) { + length += array.length; + } + float[] result = new float[length]; + int pos = 0; + for (float[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + @Beta + public static Converter stringConverter() { + return FloatConverter.INSTANCE; + } + + public static float[] ensureCapacity(float[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Floats.copyOf(array, minLength + padding) : array; + } + + private static float[] copyOf(float[] original, int length) { + float[] copy = new float[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, float ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 12); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static float[] toArray(Collection collection) { + if (collection instanceof FloatArrayAsList) { + return ((FloatArrayAsList)collection).toFloatArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + float[] array = new float[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).floatValue(); + } + return array; + } + + public static List asList(float ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new FloatArrayAsList(backingArray); + } + + @Nullable + @GwtIncompatible(value="regular expressions") + @Beta + public static Float tryParse(String string) { + if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) { + try { + return Float.valueOf(Float.parseFloat(string)); + } + catch (NumberFormatException numberFormatException) { + // empty catch block + } + } + return null; + } + + @GwtCompatible + private static class FloatArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final float[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + FloatArrayAsList(float[] array) { + this(array, 0, array.length); + } + + FloatArrayAsList(float[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Float get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return Float.valueOf(this.array[this.start + index]); + } + + @Override + public boolean contains(Object target) { + return target instanceof Float && Floats.indexOf(this.array, ((Float)target).floatValue(), this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Float && (i = Floats.indexOf(this.array, ((Float)target).floatValue(), this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Float && (i = Floats.lastIndexOf(this.array, ((Float)target).floatValue(), this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Float set(int index, Float element) { + Preconditions.checkElementIndex(index, this.size()); + float oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element).floatValue(); + return Float.valueOf(oldValue); + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new FloatArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof FloatArrayAsList) { + FloatArrayAsList that = (FloatArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Floats.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 12); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + float[] toFloatArray() { + int size = this.size(); + float[] result = new float[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(float[] left, float[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Float.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + private static final class FloatConverter + extends Converter + implements Serializable { + static final FloatConverter INSTANCE = new FloatConverter(); + private static final long serialVersionUID = 1L; + + private FloatConverter() { + } + + @Override + protected Float doForward(String value) { + return Float.valueOf(value); + } + + @Override + protected String doBackward(Float value) { + return value.toString(); + } + + public String toString() { + return "Floats.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/primitives/Ints.java b/src/com/google/common/primitives/Ints.java new file mode 100644 index 0000000..d9a6360 --- /dev/null +++ b/src/com/google/common/primitives/Ints.java @@ -0,0 +1,438 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.CheckForNull; + +@GwtCompatible(emulated=true) +public final class Ints { + public static final int BYTES = 4; + public static final int MAX_POWER_OF_TWO = 0x40000000; + private static final byte[] asciiDigits; + + private Ints() { + } + + public static int hashCode(int value) { + return value; + } + + public static int checkedCast(long value) { + int result = (int)value; + if ((long)result != value) { + long l = value; + throw new IllegalArgumentException(new StringBuilder(34).append("Out of range: ").append(l).toString()); + } + return result; + } + + public static int saturatedCast(long value) { + if (value > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + if (value < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + return (int)value; + } + + public static int compare(int a, int b) { + return a < b ? -1 : (a > b ? 1 : 0); + } + + public static boolean contains(int[] array, int target) { + for (int value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(int[] array, int target) { + return Ints.indexOf(array, target, 0, array.length); + } + + private static int indexOf(int[] array, int target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(int[] array, int[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(int[] array, int target) { + return Ints.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(int[] array, int target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int min(int ... array) { + Preconditions.checkArgument(array.length > 0); + int min = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] >= min) continue; + min = array[i]; + } + return min; + } + + public static int max(int ... array) { + Preconditions.checkArgument(array.length > 0); + int max = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] <= max) continue; + max = array[i]; + } + return max; + } + + public static int[] concat(int[] ... arrays) { + int length = 0; + for (int[] array : arrays) { + length += array.length; + } + int[] result = new int[length]; + int pos = 0; + for (int[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + @GwtIncompatible(value="doesn't work") + public static byte[] toByteArray(int value) { + return new byte[]{(byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)value}; + } + + @GwtIncompatible(value="doesn't work") + public static int fromByteArray(byte[] bytes) { + Preconditions.checkArgument(bytes.length >= 4, "array too small: %s < %s", bytes.length, 4); + return Ints.fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]); + } + + @GwtIncompatible(value="doesn't work") + public static int fromBytes(byte b1, byte b2, byte b3, byte b4) { + return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | b4 & 0xFF; + } + + @Beta + public static Converter stringConverter() { + return IntConverter.INSTANCE; + } + + public static int[] ensureCapacity(int[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Ints.copyOf(array, minLength + padding) : array; + } + + private static int[] copyOf(int[] original, int length) { + int[] copy = new int[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, int ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static int[] toArray(Collection collection) { + if (collection instanceof IntArrayAsList) { + return ((IntArrayAsList)collection).toIntArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + int[] array = new int[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).intValue(); + } + return array; + } + + public static List asList(int ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new IntArrayAsList(backingArray); + } + + private static int digit(char c) { + return c < '\u0080' ? asciiDigits[c] : -1; + } + + @CheckForNull + @Beta + public static Integer tryParse(String string) { + return Ints.tryParse(string, 10); + } + + @CheckForNull + static Integer tryParse(String string, int radix) { + int digit; + int index; + if (Preconditions.checkNotNull(string).isEmpty()) { + return null; + } + if (radix < 2 || radix > 36) { + int n = radix; + throw new IllegalArgumentException(new StringBuilder(65).append("radix must be between MIN_RADIX and MAX_RADIX but was ").append(n).toString()); + } + boolean negative = string.charAt(0) == '-'; + int n = index = negative ? 1 : 0; + if (index == string.length()) { + return null; + } + if ((digit = Ints.digit(string.charAt(index++))) < 0 || digit >= radix) { + return null; + } + int accum = -digit; + int cap = Integer.MIN_VALUE / radix; + while (index < string.length()) { + if ((digit = Ints.digit(string.charAt(index++))) < 0 || digit >= radix || accum < cap) { + return null; + } + if ((accum *= radix) < Integer.MIN_VALUE + digit) { + return null; + } + accum -= digit; + } + if (negative) { + return accum; + } + if (accum == Integer.MIN_VALUE) { + return null; + } + return -accum; + } + + static { + int i; + asciiDigits = new byte[128]; + Arrays.fill(asciiDigits, (byte)-1); + for (i = 0; i <= 9; ++i) { + Ints.asciiDigits[48 + i] = (byte)i; + } + for (i = 0; i <= 26; ++i) { + Ints.asciiDigits[65 + i] = (byte)(10 + i); + Ints.asciiDigits[97 + i] = (byte)(10 + i); + } + } + + @GwtCompatible + private static class IntArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final int[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + IntArrayAsList(int[] array) { + this(array, 0, array.length); + } + + IntArrayAsList(int[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Integer get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Integer && Ints.indexOf(this.array, (Integer)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Integer && (i = Ints.indexOf(this.array, (Integer)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Integer && (i = Ints.lastIndexOf(this.array, (Integer)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Integer set(int index, Integer element) { + Preconditions.checkElementIndex(index, this.size()); + int oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new IntArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof IntArrayAsList) { + IntArrayAsList that = (IntArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Ints.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 5); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + int[] toIntArray() { + int size = this.size(); + int[] result = new int[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(int[] left, int[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Ints.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + private static final class IntConverter + extends Converter + implements Serializable { + static final IntConverter INSTANCE = new IntConverter(); + private static final long serialVersionUID = 1L; + + private IntConverter() { + } + + @Override + protected Integer doForward(String value) { + return Integer.decode(value); + } + + @Override + protected String doBackward(Integer value) { + return value.toString(); + } + + public String toString() { + return "Ints.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/primitives/Longs.java b/src/com/google/common/primitives/Longs.java new file mode 100644 index 0000000..63487d0 --- /dev/null +++ b/src/com/google/common/primitives/Longs.java @@ -0,0 +1,389 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + +@GwtCompatible +public final class Longs { + public static final int BYTES = 8; + public static final long MAX_POWER_OF_TWO = 0x4000000000000000L; + + private Longs() { + } + + public static int hashCode(long value) { + return (int)(value ^ value >>> 32); + } + + public static int compare(long a, long b) { + return a < b ? -1 : (a > b ? 1 : 0); + } + + public static boolean contains(long[] array, long target) { + for (long value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(long[] array, long target) { + return Longs.indexOf(array, target, 0, array.length); + } + + private static int indexOf(long[] array, long target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(long[] array, long[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(long[] array, long target) { + return Longs.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(long[] array, long target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static long min(long ... array) { + Preconditions.checkArgument(array.length > 0); + long min = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] >= min) continue; + min = array[i]; + } + return min; + } + + public static long max(long ... array) { + Preconditions.checkArgument(array.length > 0); + long max = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] <= max) continue; + max = array[i]; + } + return max; + } + + public static long[] concat(long[] ... arrays) { + int length = 0; + for (long[] array : arrays) { + length += array.length; + } + long[] result = new long[length]; + int pos = 0; + for (long[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + public static byte[] toByteArray(long value) { + byte[] result = new byte[8]; + for (int i = 7; i >= 0; --i) { + result[i] = (byte)(value & 0xFFL); + value >>= 8; + } + return result; + } + + public static long fromByteArray(byte[] bytes) { + Preconditions.checkArgument(bytes.length >= 8, "array too small: %s < %s", bytes.length, 8); + return Longs.fromBytes(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]); + } + + public static long fromBytes(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8) { + return ((long)b1 & 0xFFL) << 56 | ((long)b2 & 0xFFL) << 48 | ((long)b3 & 0xFFL) << 40 | ((long)b4 & 0xFFL) << 32 | ((long)b5 & 0xFFL) << 24 | ((long)b6 & 0xFFL) << 16 | ((long)b7 & 0xFFL) << 8 | (long)b8 & 0xFFL; + } + + @Beta + public static Long tryParse(String string) { + int digit; + int index; + if (Preconditions.checkNotNull(string).isEmpty()) { + return null; + } + boolean negative = string.charAt(0) == '-'; + int n = index = negative ? 1 : 0; + if (index == string.length()) { + return null; + } + if ((digit = string.charAt(index++) - 48) < 0 || digit > 9) { + return null; + } + long accum = -digit; + while (index < string.length()) { + if ((digit = string.charAt(index++) - 48) < 0 || digit > 9 || accum < -922337203685477580L) { + return null; + } + if ((accum *= 10L) < Long.MIN_VALUE + (long)digit) { + return null; + } + accum -= (long)digit; + } + if (negative) { + return accum; + } + if (accum == Long.MIN_VALUE) { + return null; + } + return -accum; + } + + @Beta + public static Converter stringConverter() { + return LongConverter.INSTANCE; + } + + public static long[] ensureCapacity(long[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Longs.copyOf(array, minLength + padding) : array; + } + + private static long[] copyOf(long[] original, int length) { + long[] copy = new long[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, long ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 10); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static long[] toArray(Collection collection) { + if (collection instanceof LongArrayAsList) { + return ((LongArrayAsList)collection).toLongArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + long[] array = new long[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).longValue(); + } + return array; + } + + public static List asList(long ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new LongArrayAsList(backingArray); + } + + @GwtCompatible + private static class LongArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final long[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + LongArrayAsList(long[] array) { + this(array, 0, array.length); + } + + LongArrayAsList(long[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Long get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Long && Longs.indexOf(this.array, (Long)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Long && (i = Longs.indexOf(this.array, (Long)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Long && (i = Longs.lastIndexOf(this.array, (Long)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Long set(int index, Long element) { + Preconditions.checkElementIndex(index, this.size()); + long oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new LongArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof LongArrayAsList) { + LongArrayAsList that = (LongArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Longs.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 10); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + long[] toLongArray() { + int size = this.size(); + long[] result = new long[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(long[] left, long[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Longs.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + private static final class LongConverter + extends Converter + implements Serializable { + static final LongConverter INSTANCE = new LongConverter(); + private static final long serialVersionUID = 1L; + + private LongConverter() { + } + + @Override + protected Long doForward(String value) { + return Long.decode(value); + } + + @Override + protected String doBackward(Long value) { + return value.toString(); + } + + public String toString() { + return "Longs.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/primitives/ParseRequest.java b/src/com/google/common/primitives/ParseRequest.java new file mode 100644 index 0000000..95f4c68 --- /dev/null +++ b/src/com/google/common/primitives/ParseRequest.java @@ -0,0 +1,40 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +final class ParseRequest { + final String rawValue; + final int radix; + + private ParseRequest(String rawValue, int radix) { + this.rawValue = rawValue; + this.radix = radix; + } + + static ParseRequest fromString(String stringValue) { + int radix; + String rawValue; + if (stringValue.length() == 0) { + throw new NumberFormatException("empty string"); + } + char firstChar = stringValue.charAt(0); + if (stringValue.startsWith("0x") || stringValue.startsWith("0X")) { + rawValue = stringValue.substring(2); + radix = 16; + } else if (firstChar == '#') { + rawValue = stringValue.substring(1); + radix = 16; + } else if (firstChar == '0' && stringValue.length() > 1) { + rawValue = stringValue.substring(1); + radix = 8; + } else { + rawValue = stringValue; + radix = 10; + } + return new ParseRequest(rawValue, radix); + } +} diff --git a/src/com/google/common/primitives/Primitives.java b/src/com/google/common/primitives/Primitives.java new file mode 100644 index 0000000..d9626e2 --- /dev/null +++ b/src/com/google/common/primitives/Primitives.java @@ -0,0 +1,63 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public final class Primitives { + private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPE; + + private Primitives() { + } + + private static void add(Map, Class> forward, Map, Class> backward, Class key, Class value) { + forward.put(key, value); + backward.put(value, key); + } + + public static Set> allPrimitiveTypes() { + return PRIMITIVE_TO_WRAPPER_TYPE.keySet(); + } + + public static Set> allWrapperTypes() { + return WRAPPER_TO_PRIMITIVE_TYPE.keySet(); + } + + public static boolean isWrapperType(Class type) { + return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(Preconditions.checkNotNull(type)); + } + + public static Class wrap(Class type) { + Preconditions.checkNotNull(type); + Class wrapped = PRIMITIVE_TO_WRAPPER_TYPE.get(type); + return wrapped == null ? type : wrapped; + } + + public static Class unwrap(Class type) { + Preconditions.checkNotNull(type); + Class unwrapped = WRAPPER_TO_PRIMITIVE_TYPE.get(type); + return unwrapped == null ? type : unwrapped; + } + + static { + HashMap primToWrap = new HashMap(16); + HashMap wrapToPrim = new HashMap(16); + Primitives.add(primToWrap, wrapToPrim, Boolean.TYPE, Boolean.class); + Primitives.add(primToWrap, wrapToPrim, Byte.TYPE, Byte.class); + Primitives.add(primToWrap, wrapToPrim, Character.TYPE, Character.class); + Primitives.add(primToWrap, wrapToPrim, Double.TYPE, Double.class); + Primitives.add(primToWrap, wrapToPrim, Float.TYPE, Float.class); + Primitives.add(primToWrap, wrapToPrim, Integer.TYPE, Integer.class); + Primitives.add(primToWrap, wrapToPrim, Long.TYPE, Long.class); + Primitives.add(primToWrap, wrapToPrim, Short.TYPE, Short.class); + Primitives.add(primToWrap, wrapToPrim, Void.TYPE, Void.class); + PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim); + } +} diff --git a/src/com/google/common/primitives/Shorts.java b/src/com/google/common/primitives/Shorts.java new file mode 100644 index 0000000..e9f80bf --- /dev/null +++ b/src/com/google/common/primitives/Shorts.java @@ -0,0 +1,373 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + +@GwtCompatible(emulated=true) +public final class Shorts { + public static final int BYTES = 2; + public static final short MAX_POWER_OF_TWO = 16384; + + private Shorts() { + } + + public static int hashCode(short value) { + return value; + } + + public static short checkedCast(long value) { + short result = (short)value; + if ((long)result != value) { + long l = value; + throw new IllegalArgumentException(new StringBuilder(34).append("Out of range: ").append(l).toString()); + } + return result; + } + + public static short saturatedCast(long value) { + if (value > 32767L) { + return Short.MAX_VALUE; + } + if (value < -32768L) { + return Short.MIN_VALUE; + } + return (short)value; + } + + public static int compare(short a, short b) { + return a - b; + } + + public static boolean contains(short[] array, short target) { + for (short value : array) { + if (value != target) continue; + return true; + } + return false; + } + + public static int indexOf(short[] array, short target) { + return Shorts.indexOf(array, target, 0, array.length); + } + + private static int indexOf(short[] array, short target, int start, int end) { + for (int i = start; i < end; ++i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static int indexOf(short[] array, short[] target) { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + block0: for (int i = 0; i < array.length - target.length + 1; ++i) { + for (int j = 0; j < target.length; ++j) { + if (array[i + j] != target[j]) continue block0; + } + return i; + } + return -1; + } + + public static int lastIndexOf(short[] array, short target) { + return Shorts.lastIndexOf(array, target, 0, array.length); + } + + private static int lastIndexOf(short[] array, short target, int start, int end) { + for (int i = end - 1; i >= start; --i) { + if (array[i] != target) continue; + return i; + } + return -1; + } + + public static short min(short ... array) { + Preconditions.checkArgument(array.length > 0); + short min = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] >= min) continue; + min = array[i]; + } + return min; + } + + public static short max(short ... array) { + Preconditions.checkArgument(array.length > 0); + short max = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] <= max) continue; + max = array[i]; + } + return max; + } + + public static short[] concat(short[] ... arrays) { + int length = 0; + for (short[] array : arrays) { + length += array.length; + } + short[] result = new short[length]; + int pos = 0; + for (short[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + @GwtIncompatible(value="doesn't work") + public static byte[] toByteArray(short value) { + return new byte[]{(byte)(value >> 8), (byte)value}; + } + + @GwtIncompatible(value="doesn't work") + public static short fromByteArray(byte[] bytes) { + Preconditions.checkArgument(bytes.length >= 2, "array too small: %s < %s", bytes.length, 2); + return Shorts.fromBytes(bytes[0], bytes[1]); + } + + @GwtIncompatible(value="doesn't work") + public static short fromBytes(byte b1, byte b2) { + return (short)(b1 << 8 | b2 & 0xFF); + } + + @Beta + public static Converter stringConverter() { + return ShortConverter.INSTANCE; + } + + public static short[] ensureCapacity(short[] array, int minLength, int padding) { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding); + return array.length < minLength ? Shorts.copyOf(array, minLength + padding) : array; + } + + private static short[] copyOf(short[] original, int length) { + short[] copy = new short[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + public static String join(String separator, short ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 6); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static short[] toArray(Collection collection) { + if (collection instanceof ShortArrayAsList) { + return ((ShortArrayAsList)collection).toShortArray(); + } + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + short[] array = new short[len]; + for (int i = 0; i < len; ++i) { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).shortValue(); + } + return array; + } + + public static List asList(short ... backingArray) { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new ShortArrayAsList(backingArray); + } + + @GwtCompatible + private static class ShortArrayAsList + extends AbstractList + implements RandomAccess, + Serializable { + final short[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + ShortArrayAsList(short[] array) { + this(array, 0, array.length); + } + + ShortArrayAsList(short[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + @Override + public int size() { + return this.end - this.start; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public Short get(int index) { + Preconditions.checkElementIndex(index, this.size()); + return this.array[this.start + index]; + } + + @Override + public boolean contains(Object target) { + return target instanceof Short && Shorts.indexOf(this.array, (Short)target, this.start, this.end) != -1; + } + + @Override + public int indexOf(Object target) { + int i; + if (target instanceof Short && (i = Shorts.indexOf(this.array, (Short)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public int lastIndexOf(Object target) { + int i; + if (target instanceof Short && (i = Shorts.lastIndexOf(this.array, (Short)target, this.start, this.end)) >= 0) { + return i - this.start; + } + return -1; + } + + @Override + public Short set(int index, Short element) { + Preconditions.checkElementIndex(index, this.size()); + short oldValue = this.array[this.start + index]; + this.array[this.start + index] = Preconditions.checkNotNull(element); + return oldValue; + } + + @Override + public List subList(int fromIndex, int toIndex) { + int size = this.size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new ShortArrayAsList(this.array, this.start + fromIndex, this.start + toIndex); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object instanceof ShortArrayAsList) { + ShortArrayAsList that = (ShortArrayAsList)object; + int size = this.size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; ++i) { + if (this.array[this.start + i] == that.array[that.start + i]) continue; + return false; + } + return true; + } + return super.equals(object); + } + + @Override + public int hashCode() { + int result = 1; + for (int i = this.start; i < this.end; ++i) { + result = 31 * result + Shorts.hashCode(this.array[i]); + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(this.size() * 6); + builder.append('[').append(this.array[this.start]); + for (int i = this.start + 1; i < this.end; ++i) { + builder.append(", ").append(this.array[i]); + } + return builder.append(']').toString(); + } + + short[] toShortArray() { + int size = this.size(); + short[] result = new short[size]; + System.arraycopy(this.array, this.start, result, 0, size); + return result; + } + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(short[] left, short[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = Shorts.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + private static final class ShortConverter + extends Converter + implements Serializable { + static final ShortConverter INSTANCE = new ShortConverter(); + private static final long serialVersionUID = 1L; + + private ShortConverter() { + } + + @Override + protected Short doForward(String value) { + return Short.decode(value); + } + + @Override + protected String doBackward(Short value) { + return value.toString(); + } + + public String toString() { + return "Shorts.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/com/google/common/primitives/SignedBytes.java b/src/com/google/common/primitives/SignedBytes.java new file mode 100644 index 0000000..ff3a6c3 --- /dev/null +++ b/src/com/google/common/primitives/SignedBytes.java @@ -0,0 +1,93 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; + +@GwtCompatible +public final class SignedBytes { + public static final byte MAX_POWER_OF_TWO = 64; + + private SignedBytes() { + } + + public static byte checkedCast(long value) { + byte result = (byte)value; + if ((long)result != value) { + long l = value; + throw new IllegalArgumentException(new StringBuilder(34).append("Out of range: ").append(l).toString()); + } + return result; + } + + public static byte saturatedCast(long value) { + if (value > 127L) { + return 127; + } + if (value < -128L) { + return -128; + } + return (byte)value; + } + + public static int compare(byte a, byte b) { + return a - b; + } + + public static byte min(byte ... array) { + Preconditions.checkArgument(array.length > 0); + byte min = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] >= min) continue; + min = array[i]; + } + return min; + } + + public static byte max(byte ... array) { + Preconditions.checkArgument(array.length > 0); + byte max = array[0]; + for (int i = 1; i < array.length; ++i) { + if (array[i] <= max) continue; + max = array[i]; + } + return max; + } + + public static String join(String separator, byte ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(array[0]); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(byte[] left, byte[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = SignedBytes.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } +} diff --git a/src/com/google/common/primitives/UnsignedBytes.java b/src/com/google/common/primitives/UnsignedBytes.java new file mode 100644 index 0000000..e963b95 --- /dev/null +++ b/src/com/google/common/primitives/UnsignedBytes.java @@ -0,0 +1,227 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.primitives.UnsignedLongs; +import java.lang.reflect.Field; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Comparator; +import sun.misc.Unsafe; + +public final class UnsignedBytes { + public static final byte MAX_POWER_OF_TWO = -128; + public static final byte MAX_VALUE = -1; + private static final int UNSIGNED_MASK = 255; + + private UnsignedBytes() { + } + + public static int toInt(byte value) { + return value & 0xFF; + } + + public static byte checkedCast(long value) { + if (value >> 8 != 0L) { + long l = value; + throw new IllegalArgumentException(new StringBuilder(34).append("Out of range: ").append(l).toString()); + } + return (byte)value; + } + + public static byte saturatedCast(long value) { + if (value > (long)UnsignedBytes.toInt((byte)-1)) { + return -1; + } + if (value < 0L) { + return 0; + } + return (byte)value; + } + + public static int compare(byte a, byte b) { + return UnsignedBytes.toInt(a) - UnsignedBytes.toInt(b); + } + + public static byte min(byte ... array) { + Preconditions.checkArgument(array.length > 0); + int min = UnsignedBytes.toInt(array[0]); + for (int i = 1; i < array.length; ++i) { + int next = UnsignedBytes.toInt(array[i]); + if (next >= min) continue; + min = next; + } + return (byte)min; + } + + public static byte max(byte ... array) { + Preconditions.checkArgument(array.length > 0); + int max = UnsignedBytes.toInt(array[0]); + for (int i = 1; i < array.length; ++i) { + int next = UnsignedBytes.toInt(array[i]); + if (next <= max) continue; + max = next; + } + return (byte)max; + } + + @Beta + public static String toString(byte x) { + return UnsignedBytes.toString(x, 10); + } + + @Beta + public static String toString(byte x, int radix) { + Preconditions.checkArgument(radix >= 2 && radix <= 36, "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix); + return Integer.toString(UnsignedBytes.toInt(x), radix); + } + + @Beta + public static byte parseUnsignedByte(String string) { + return UnsignedBytes.parseUnsignedByte(string, 10); + } + + @Beta + public static byte parseUnsignedByte(String string, int radix) { + int parse = Integer.parseInt(Preconditions.checkNotNull(string), radix); + if (parse >> 8 == 0) { + return (byte)parse; + } + int n = parse; + throw new NumberFormatException(new StringBuilder(25).append("out of range: ").append(n).toString()); + } + + public static String join(String separator, byte ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * (3 + separator.length())); + builder.append(UnsignedBytes.toInt(array[0])); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(UnsignedBytes.toString(array[i])); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparatorHolder.BEST_COMPARATOR; + } + + @VisibleForTesting + static Comparator lexicographicalComparatorJavaImpl() { + return LexicographicalComparatorHolder.PureJavaComparator.INSTANCE; + } + + @VisibleForTesting + static class LexicographicalComparatorHolder { + static final String UNSAFE_COMPARATOR_NAME = String.valueOf(LexicographicalComparatorHolder.class.getName()).concat("$UnsafeComparator"); + static final Comparator BEST_COMPARATOR = LexicographicalComparatorHolder.getBestComparator(); + + LexicographicalComparatorHolder() { + } + + static Comparator getBestComparator() { + try { + Class theClass = Class.forName(UNSAFE_COMPARATOR_NAME); + Comparator comparator = (Comparator)theClass.getEnumConstants()[0]; + return comparator; + } + catch (Throwable t) { + return UnsignedBytes.lexicographicalComparatorJavaImpl(); + } + } + + static enum PureJavaComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(byte[] left, byte[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + int result = UnsignedBytes.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + } + + @VisibleForTesting + static enum UnsafeComparator implements Comparator + { + INSTANCE; + + static final boolean BIG_ENDIAN; + static final Unsafe theUnsafe; + static final int BYTE_ARRAY_BASE_OFFSET; + + private static Unsafe getUnsafe() { + try { + return Unsafe.getUnsafe(); + } + catch (SecurityException tryReflectionInstead) { + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction(){ + + @Override + public Unsafe run() throws Exception { + Class k = Unsafe.class; + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (!k.isInstance(x)) continue; + return (Unsafe)k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + } + }); + } + catch (PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", e.getCause()); + } + } + } + + @Override + public int compare(byte[] left, byte[] right) { + int i; + int minLength = Math.min(left.length, right.length); + int minWords = minLength / 8; + for (i = 0; i < minWords * 8; i += 8) { + long rw; + long lw = theUnsafe.getLong(left, (long)BYTE_ARRAY_BASE_OFFSET + (long)i); + if (lw == (rw = theUnsafe.getLong(right, (long)BYTE_ARRAY_BASE_OFFSET + (long)i))) continue; + if (BIG_ENDIAN) { + return UnsignedLongs.compare(lw, rw); + } + int n = Long.numberOfTrailingZeros(lw ^ rw) & 0xFFFFFFF8; + return (int)((lw >>> n & 0xFFL) - (rw >>> n & 0xFFL)); + } + for (i = minWords * 8; i < minLength; ++i) { + int result = UnsignedBytes.compare(left[i], right[i]); + if (result == 0) continue; + return result; + } + return left.length - right.length; + } + + static { + BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); + theUnsafe = UnsafeComparator.getUnsafe(); + BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class); + if (theUnsafe.arrayIndexScale(byte[].class) != 1) { + throw new AssertionError(); + } + } + } + } +} diff --git a/src/com/google/common/primitives/UnsignedInteger.java b/src/com/google/common/primitives/UnsignedInteger.java new file mode 100644 index 0000000..636c66d --- /dev/null +++ b/src/com/google/common/primitives/UnsignedInteger.java @@ -0,0 +1,125 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.UnsignedInts; +import java.math.BigInteger; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@GwtCompatible(emulated=true) +public final class UnsignedInteger +extends Number +implements Comparable { + public static final UnsignedInteger ZERO = UnsignedInteger.fromIntBits(0); + public static final UnsignedInteger ONE = UnsignedInteger.fromIntBits(1); + public static final UnsignedInteger MAX_VALUE = UnsignedInteger.fromIntBits(-1); + private final int value; + + private UnsignedInteger(int value) { + this.value = value & 0xFFFFFFFF; + } + + public static UnsignedInteger fromIntBits(int bits) { + return new UnsignedInteger(bits); + } + + public static UnsignedInteger valueOf(long value) { + Preconditions.checkArgument((value & 0xFFFFFFFFL) == value, "value (%s) is outside the range for an unsigned integer value", value); + return UnsignedInteger.fromIntBits((int)value); + } + + public static UnsignedInteger valueOf(BigInteger value) { + Preconditions.checkNotNull(value); + Preconditions.checkArgument(value.signum() >= 0 && value.bitLength() <= 32, "value (%s) is outside the range for an unsigned integer value", value); + return UnsignedInteger.fromIntBits(value.intValue()); + } + + public static UnsignedInteger valueOf(String string) { + return UnsignedInteger.valueOf(string, 10); + } + + public static UnsignedInteger valueOf(String string, int radix) { + return UnsignedInteger.fromIntBits(UnsignedInts.parseUnsignedInt(string, radix)); + } + + @CheckReturnValue + public UnsignedInteger plus(UnsignedInteger val) { + return UnsignedInteger.fromIntBits(this.value + Preconditions.checkNotNull(val).value); + } + + @CheckReturnValue + public UnsignedInteger minus(UnsignedInteger val) { + return UnsignedInteger.fromIntBits(this.value - Preconditions.checkNotNull(val).value); + } + + @CheckReturnValue + @GwtIncompatible(value="Does not truncate correctly") + public UnsignedInteger times(UnsignedInteger val) { + return UnsignedInteger.fromIntBits(this.value * Preconditions.checkNotNull(val).value); + } + + @CheckReturnValue + public UnsignedInteger dividedBy(UnsignedInteger val) { + return UnsignedInteger.fromIntBits(UnsignedInts.divide(this.value, Preconditions.checkNotNull(val).value)); + } + + @CheckReturnValue + public UnsignedInteger mod(UnsignedInteger val) { + return UnsignedInteger.fromIntBits(UnsignedInts.remainder(this.value, Preconditions.checkNotNull(val).value)); + } + + @Override + public int intValue() { + return this.value; + } + + @Override + public long longValue() { + return UnsignedInts.toLong(this.value); + } + + @Override + public float floatValue() { + return this.longValue(); + } + + @Override + public double doubleValue() { + return this.longValue(); + } + + public BigInteger bigIntegerValue() { + return BigInteger.valueOf(this.longValue()); + } + + @Override + public int compareTo(UnsignedInteger other) { + Preconditions.checkNotNull(other); + return UnsignedInts.compare(this.value, other.value); + } + + public int hashCode() { + return this.value; + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof UnsignedInteger) { + UnsignedInteger other = (UnsignedInteger)obj; + return this.value == other.value; + } + return false; + } + + public String toString() { + return this.toString(10); + } + + public String toString(int radix) { + return UnsignedInts.toString(this.value, radix); + } +} diff --git a/src/com/google/common/primitives/UnsignedInts.java b/src/com/google/common/primitives/UnsignedInts.java new file mode 100644 index 0000000..570d761 --- /dev/null +++ b/src/com/google/common/primitives/UnsignedInts.java @@ -0,0 +1,132 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import com.google.common.primitives.ParseRequest; +import java.util.Comparator; + +@Beta +@GwtCompatible +public final class UnsignedInts { + static final long INT_MASK = 0xFFFFFFFFL; + + private UnsignedInts() { + } + + static int flip(int value) { + return value ^ Integer.MIN_VALUE; + } + + public static int compare(int a, int b) { + return Ints.compare(UnsignedInts.flip(a), UnsignedInts.flip(b)); + } + + public static long toLong(int value) { + return (long)value & 0xFFFFFFFFL; + } + + public static int min(int ... array) { + Preconditions.checkArgument(array.length > 0); + int min = UnsignedInts.flip(array[0]); + for (int i = 1; i < array.length; ++i) { + int next = UnsignedInts.flip(array[i]); + if (next >= min) continue; + min = next; + } + return UnsignedInts.flip(min); + } + + public static int max(int ... array) { + Preconditions.checkArgument(array.length > 0); + int max = UnsignedInts.flip(array[0]); + for (int i = 1; i < array.length; ++i) { + int next = UnsignedInts.flip(array[i]); + if (next <= max) continue; + max = next; + } + return UnsignedInts.flip(max); + } + + public static String join(String separator, int ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(UnsignedInts.toString(array[0])); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(UnsignedInts.toString(array[i])); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static int divide(int dividend, int divisor) { + return (int)(UnsignedInts.toLong(dividend) / UnsignedInts.toLong(divisor)); + } + + public static int remainder(int dividend, int divisor) { + return (int)(UnsignedInts.toLong(dividend) % UnsignedInts.toLong(divisor)); + } + + public static int decode(String stringValue) { + ParseRequest request = ParseRequest.fromString(stringValue); + try { + return UnsignedInts.parseUnsignedInt(request.rawValue, request.radix); + } + catch (NumberFormatException e) { + String string = String.valueOf(stringValue); + NumberFormatException decodeException = new NumberFormatException(string.length() != 0 ? "Error parsing value: ".concat(string) : new String("Error parsing value: ")); + decodeException.initCause(e); + throw decodeException; + } + } + + public static int parseUnsignedInt(String s) { + return UnsignedInts.parseUnsignedInt(s, 10); + } + + public static int parseUnsignedInt(String string, int radix) { + Preconditions.checkNotNull(string); + long result = Long.parseLong(string, radix); + if ((result & 0xFFFFFFFFL) != result) { + String string2 = String.valueOf(String.valueOf(string)); + int n = radix; + throw new NumberFormatException(new StringBuilder(69 + string2.length()).append("Input ").append(string2).append(" in base ").append(n).append(" is not in the range of an unsigned integer").toString()); + } + return (int)result; + } + + public static String toString(int x) { + return UnsignedInts.toString(x, 10); + } + + public static String toString(int x, int radix) { + long asLong = (long)x & 0xFFFFFFFFL; + return Long.toString(asLong, radix); + } + + static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(int[] left, int[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + if (left[i] == right[i]) continue; + return UnsignedInts.compare(left[i], right[i]); + } + return left.length - right.length; + } + } +} diff --git a/src/com/google/common/primitives/UnsignedLong.java b/src/com/google/common/primitives/UnsignedLong.java new file mode 100644 index 0000000..d1e31b6 --- /dev/null +++ b/src/com/google/common/primitives/UnsignedLong.java @@ -0,0 +1,137 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Longs; +import com.google.common.primitives.UnsignedLongs; +import java.io.Serializable; +import java.math.BigInteger; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + +@GwtCompatible(serializable=true) +public final class UnsignedLong +extends Number +implements Comparable, +Serializable { + private static final long UNSIGNED_MASK = Long.MAX_VALUE; + public static final UnsignedLong ZERO = new UnsignedLong(0L); + public static final UnsignedLong ONE = new UnsignedLong(1L); + public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L); + private final long value; + + private UnsignedLong(long value) { + this.value = value; + } + + public static UnsignedLong fromLongBits(long bits) { + return new UnsignedLong(bits); + } + + public static UnsignedLong valueOf(long value) { + Preconditions.checkArgument(value >= 0L, "value (%s) is outside the range for an unsigned long value", value); + return UnsignedLong.fromLongBits(value); + } + + public static UnsignedLong valueOf(BigInteger value) { + Preconditions.checkNotNull(value); + Preconditions.checkArgument(value.signum() >= 0 && value.bitLength() <= 64, "value (%s) is outside the range for an unsigned long value", value); + return UnsignedLong.fromLongBits(value.longValue()); + } + + public static UnsignedLong valueOf(String string) { + return UnsignedLong.valueOf(string, 10); + } + + public static UnsignedLong valueOf(String string, int radix) { + return UnsignedLong.fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix)); + } + + public UnsignedLong plus(UnsignedLong val) { + return UnsignedLong.fromLongBits(this.value + Preconditions.checkNotNull(val).value); + } + + public UnsignedLong minus(UnsignedLong val) { + return UnsignedLong.fromLongBits(this.value - Preconditions.checkNotNull(val).value); + } + + @CheckReturnValue + public UnsignedLong times(UnsignedLong val) { + return UnsignedLong.fromLongBits(this.value * Preconditions.checkNotNull(val).value); + } + + @CheckReturnValue + public UnsignedLong dividedBy(UnsignedLong val) { + return UnsignedLong.fromLongBits(UnsignedLongs.divide(this.value, Preconditions.checkNotNull(val).value)); + } + + @CheckReturnValue + public UnsignedLong mod(UnsignedLong val) { + return UnsignedLong.fromLongBits(UnsignedLongs.remainder(this.value, Preconditions.checkNotNull(val).value)); + } + + @Override + public int intValue() { + return (int)this.value; + } + + @Override + public long longValue() { + return this.value; + } + + @Override + public float floatValue() { + float fValue = this.value & Long.MAX_VALUE; + if (this.value < 0L) { + fValue += 9.223372E18f; + } + return fValue; + } + + @Override + public double doubleValue() { + double dValue = this.value & Long.MAX_VALUE; + if (this.value < 0L) { + dValue += 9.223372036854776E18; + } + return dValue; + } + + public BigInteger bigIntegerValue() { + BigInteger bigInt = BigInteger.valueOf(this.value & Long.MAX_VALUE); + if (this.value < 0L) { + bigInt = bigInt.setBit(63); + } + return bigInt; + } + + @Override + public int compareTo(UnsignedLong o) { + Preconditions.checkNotNull(o); + return UnsignedLongs.compare(this.value, o.value); + } + + public int hashCode() { + return Longs.hashCode(this.value); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof UnsignedLong) { + UnsignedLong other = (UnsignedLong)obj; + return this.value == other.value; + } + return false; + } + + public String toString() { + return UnsignedLongs.toString(this.value); + } + + public String toString(int radix) { + return UnsignedLongs.toString(this.value, radix); + } +} diff --git a/src/com/google/common/primitives/UnsignedLongs.java b/src/com/google/common/primitives/UnsignedLongs.java new file mode 100644 index 0000000..2610ad7 --- /dev/null +++ b/src/com/google/common/primitives/UnsignedLongs.java @@ -0,0 +1,205 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Longs; +import com.google.common.primitives.ParseRequest; +import java.math.BigInteger; +import java.util.Comparator; + +@Beta +@GwtCompatible +public final class UnsignedLongs { + public static final long MAX_VALUE = -1L; + private static final long[] maxValueDivs = new long[37]; + private static final int[] maxValueMods = new int[37]; + private static final int[] maxSafeDigits = new int[37]; + + private UnsignedLongs() { + } + + private static long flip(long a) { + return a ^ Long.MIN_VALUE; + } + + public static int compare(long a, long b) { + return Longs.compare(UnsignedLongs.flip(a), UnsignedLongs.flip(b)); + } + + public static long min(long ... array) { + Preconditions.checkArgument(array.length > 0); + long min = UnsignedLongs.flip(array[0]); + for (int i = 1; i < array.length; ++i) { + long next = UnsignedLongs.flip(array[i]); + if (next >= min) continue; + min = next; + } + return UnsignedLongs.flip(min); + } + + public static long max(long ... array) { + Preconditions.checkArgument(array.length > 0); + long max = UnsignedLongs.flip(array[0]); + for (int i = 1; i < array.length; ++i) { + long next = UnsignedLongs.flip(array[i]); + if (next <= max) continue; + max = next; + } + return UnsignedLongs.flip(max); + } + + public static String join(String separator, long ... array) { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(UnsignedLongs.toString(array[0])); + for (int i = 1; i < array.length; ++i) { + builder.append(separator).append(UnsignedLongs.toString(array[i])); + } + return builder.toString(); + } + + public static Comparator lexicographicalComparator() { + return LexicographicalComparator.INSTANCE; + } + + public static long divide(long dividend, long divisor) { + long quotient; + if (divisor < 0L) { + if (UnsignedLongs.compare(dividend, divisor) < 0) { + return 0L; + } + return 1L; + } + if (dividend >= 0L) { + return dividend / divisor; + } + long rem = dividend - (quotient = (dividend >>> 1) / divisor << 1) * divisor; + return quotient + (long)(UnsignedLongs.compare(rem, divisor) >= 0 ? 1 : 0); + } + + public static long remainder(long dividend, long divisor) { + long rem; + if (divisor < 0L) { + if (UnsignedLongs.compare(dividend, divisor) < 0) { + return dividend; + } + return dividend - divisor; + } + if (dividend >= 0L) { + return dividend % divisor; + } + long quotient = (dividend >>> 1) / divisor << 1; + return rem - (UnsignedLongs.compare(rem = dividend - quotient * divisor, divisor) >= 0 ? divisor : 0L); + } + + public static long parseUnsignedLong(String s) { + return UnsignedLongs.parseUnsignedLong(s, 10); + } + + public static long decode(String stringValue) { + ParseRequest request = ParseRequest.fromString(stringValue); + try { + return UnsignedLongs.parseUnsignedLong(request.rawValue, request.radix); + } + catch (NumberFormatException e) { + String string = String.valueOf(stringValue); + NumberFormatException decodeException = new NumberFormatException(string.length() != 0 ? "Error parsing value: ".concat(string) : new String("Error parsing value: ")); + decodeException.initCause(e); + throw decodeException; + } + } + + public static long parseUnsignedLong(String s, int radix) { + Preconditions.checkNotNull(s); + if (s.length() == 0) { + throw new NumberFormatException("empty string"); + } + if (radix < 2 || radix > 36) { + int n = radix; + throw new NumberFormatException(new StringBuilder(26).append("illegal radix: ").append(n).toString()); + } + int max_safe_pos = maxSafeDigits[radix] - 1; + long value = 0L; + for (int pos = 0; pos < s.length(); ++pos) { + int digit = Character.digit(s.charAt(pos), radix); + if (digit == -1) { + throw new NumberFormatException(s); + } + if (pos > max_safe_pos && UnsignedLongs.overflowInParse(value, digit, radix)) { + String string = String.valueOf(s); + throw new NumberFormatException(string.length() != 0 ? "Too large for unsigned long: ".concat(string) : new String("Too large for unsigned long: ")); + } + value = value * (long)radix + (long)digit; + } + return value; + } + + private static boolean overflowInParse(long current, int digit, int radix) { + if (current >= 0L) { + if (current < maxValueDivs[radix]) { + return false; + } + if (current > maxValueDivs[radix]) { + return true; + } + return digit > maxValueMods[radix]; + } + return true; + } + + public static String toString(long x) { + return UnsignedLongs.toString(x, 10); + } + + public static String toString(long x, int radix) { + Preconditions.checkArgument(radix >= 2 && radix <= 36, "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix); + if (x == 0L) { + return "0"; + } + char[] buf = new char[64]; + int i = buf.length; + if (x < 0L) { + long quotient = UnsignedLongs.divide(x, radix); + long rem = x - quotient * (long)radix; + buf[--i] = Character.forDigit((int)rem, radix); + x = quotient; + } + while (x > 0L) { + buf[--i] = Character.forDigit((int)(x % (long)radix), radix); + x /= (long)radix; + } + return new String(buf, i, buf.length - i); + } + + static { + BigInteger overflow = new BigInteger("10000000000000000", 16); + for (int i = 2; i <= 36; ++i) { + UnsignedLongs.maxValueDivs[i] = UnsignedLongs.divide(-1L, i); + UnsignedLongs.maxValueMods[i] = (int)UnsignedLongs.remainder(-1L, i); + UnsignedLongs.maxSafeDigits[i] = overflow.toString(i).length() - 1; + } + } + + static enum LexicographicalComparator implements Comparator + { + INSTANCE; + + + @Override + public int compare(long[] left, long[] right) { + int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; ++i) { + if (left[i] == right[i]) continue; + return UnsignedLongs.compare(left[i], right[i]); + } + return left.length - right.length; + } + } +} diff --git a/src/com/google/common/primitives/package-info.java b/src/com/google/common/primitives/package-info.java new file mode 100644 index 0000000..d5be0ca --- /dev/null +++ b/src/com/google/common/primitives/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.primitives; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/reflect/AbstractInvocationHandler.java b/src/com/google/common/reflect/AbstractInvocationHandler.java new file mode 100644 index 0000000..e471de6 --- /dev/null +++ b/src/com/google/common/reflect/AbstractInvocationHandler.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import javax.annotation.Nullable; + +@Beta +public abstract class AbstractInvocationHandler +implements InvocationHandler { + private static final Object[] NO_ARGS = new Object[0]; + + @Override + public final Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { + if (args == null) { + args = NO_ARGS; + } + if (args.length == 0 && method.getName().equals("hashCode")) { + return this.hashCode(); + } + if (args.length == 1 && method.getName().equals("equals") && method.getParameterTypes()[0] == Object.class) { + Object arg = args[0]; + if (arg == null) { + return false; + } + if (proxy == arg) { + return true; + } + return AbstractInvocationHandler.isProxyOfSameInterfaces(arg, proxy.getClass()) && this.equals(Proxy.getInvocationHandler(arg)); + } + if (args.length == 0 && method.getName().equals("toString")) { + return this.toString(); + } + return this.handleInvocation(proxy, method, args); + } + + protected abstract Object handleInvocation(Object var1, Method var2, Object[] var3) throws Throwable; + + public boolean equals(Object obj) { + return super.equals(obj); + } + + public int hashCode() { + return super.hashCode(); + } + + public String toString() { + return super.toString(); + } + + private static boolean isProxyOfSameInterfaces(Object arg, Class proxyClass) { + return proxyClass.isInstance(arg) || Proxy.isProxyClass(arg.getClass()) && Arrays.equals(arg.getClass().getInterfaces(), proxyClass.getInterfaces()); + } +} diff --git a/src/com/google/common/reflect/ClassPath.java b/src/com/google/common/reflect/ClassPath.java new file mode 100644 index 0000000..367843e --- /dev/null +++ b/src/com/google/common/reflect/ClassPath.java @@ -0,0 +1,342 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import com.google.common.reflect.Reflection; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +@Beta +public final class ClassPath { + private static final Logger logger = Logger.getLogger(ClassPath.class.getName()); + private static final Predicate IS_TOP_LEVEL = new Predicate(){ + + @Override + public boolean apply(ClassInfo info) { + return info.className.indexOf(36) == -1; + } + }; + private static final Splitter CLASS_PATH_ATTRIBUTE_SEPARATOR = Splitter.on(" ").omitEmptyStrings(); + private static final String CLASS_FILE_NAME_EXTENSION = ".class"; + private final ImmutableSet resources; + + private ClassPath(ImmutableSet resources) { + this.resources = resources; + } + + public static ClassPath from(ClassLoader classloader) throws IOException { + Scanner scanner = new Scanner(); + for (Map.Entry entry : ClassPath.getClassPathEntries(classloader).entrySet()) { + scanner.scan((URI)entry.getKey(), (ClassLoader)entry.getValue()); + } + return new ClassPath(scanner.getResources()); + } + + public ImmutableSet getResources() { + return this.resources; + } + + public ImmutableSet getAllClasses() { + return FluentIterable.from(this.resources).filter(ClassInfo.class).toSet(); + } + + public ImmutableSet getTopLevelClasses() { + return FluentIterable.from(this.resources).filter(ClassInfo.class).filter(IS_TOP_LEVEL).toSet(); + } + + public ImmutableSet getTopLevelClasses(String packageName) { + Preconditions.checkNotNull(packageName); + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (ClassInfo classInfo : this.getTopLevelClasses()) { + if (!classInfo.getPackageName().equals(packageName)) continue; + builder.add(classInfo); + } + return builder.build(); + } + + public ImmutableSet getTopLevelClassesRecursive(String packageName) { + Preconditions.checkNotNull(packageName); + String string = String.valueOf(String.valueOf(packageName)); + String packagePrefix = new StringBuilder(1 + string.length()).append(string).append(".").toString(); + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (ClassInfo classInfo : this.getTopLevelClasses()) { + if (!classInfo.getName().startsWith(packagePrefix)) continue; + builder.add(classInfo); + } + return builder.build(); + } + + @VisibleForTesting + static ImmutableMap getClassPathEntries(ClassLoader classloader) { + LinkedHashMap entries = Maps.newLinkedHashMap(); + ClassLoader parent = classloader.getParent(); + if (parent != null) { + entries.putAll(ClassPath.getClassPathEntries(parent)); + } + if (classloader instanceof URLClassLoader) { + URLClassLoader urlClassLoader = (URLClassLoader)classloader; + for (URL entry : urlClassLoader.getURLs()) { + URI uri; + try { + uri = entry.toURI(); + } + catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + if (entries.containsKey(uri)) continue; + entries.put(uri, classloader); + } + } + return ImmutableMap.copyOf(entries); + } + + @VisibleForTesting + static String getClassName(String filename) { + int classNameEnd = filename.length() - CLASS_FILE_NAME_EXTENSION.length(); + return filename.substring(0, classNameEnd).replace('/', '.'); + } + + @VisibleForTesting + static final class Scanner { + private final ImmutableSortedSet.Builder resources = new ImmutableSortedSet.Builder(Ordering.usingToString()); + private final Set scannedUris = Sets.newHashSet(); + + Scanner() { + } + + ImmutableSortedSet getResources() { + return this.resources.build(); + } + + void scan(URI uri, ClassLoader classloader) throws IOException { + if (uri.getScheme().equals("file") && this.scannedUris.add(uri)) { + this.scanFrom(new File(uri), classloader); + } + } + + @VisibleForTesting + void scanFrom(File file, ClassLoader classloader) throws IOException { + if (!file.exists()) { + return; + } + if (file.isDirectory()) { + this.scanDirectory(file, classloader); + } else { + this.scanJar(file, classloader); + } + } + + private void scanDirectory(File directory, ClassLoader classloader) throws IOException { + this.scanDirectory(directory, classloader, "", ImmutableSet.of()); + } + + private void scanDirectory(File directory, ClassLoader classloader, String packagePrefix, ImmutableSet ancestors) throws IOException { + File canonical = directory.getCanonicalFile(); + if (ancestors.contains(canonical)) { + return; + } + File[] files = directory.listFiles(); + if (files == null) { + String string = String.valueOf(String.valueOf(directory)); + logger.warning(new StringBuilder(22 + string.length()).append("Cannot read directory ").append(string).toString()); + return; + } + ImmutableCollection newAncestors = ((ImmutableSet.Builder)((ImmutableSet.Builder)ImmutableSet.builder().addAll(ancestors)).add(canonical)).build(); + for (File f : files) { + String resourceName; + String name = f.getName(); + if (f.isDirectory()) { + String string = String.valueOf(String.valueOf(packagePrefix)); + String string2 = String.valueOf(String.valueOf(name)); + this.scanDirectory(f, classloader, new StringBuilder(1 + string.length() + string2.length()).append(string).append(string2).append("/").toString(), (ImmutableSet)newAncestors); + continue; + } + String string = String.valueOf(packagePrefix); + String string3 = String.valueOf(name); + String string4 = resourceName = string3.length() != 0 ? string.concat(string3) : new String(string); + if (resourceName.equals("META-INF/MANIFEST.MF")) continue; + this.resources.add((Object)ResourceInfo.of(resourceName, classloader)); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private void scanJar(File file, ClassLoader classloader) throws IOException { + JarFile jarFile; + try { + jarFile = new JarFile(file); + } + catch (IOException e) { + return; + } + try { + for (URI uri : Scanner.getClassPathFromManifest(file, jarFile.getManifest())) { + this.scan(uri, classloader); + } + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() || entry.getName().equals("META-INF/MANIFEST.MF")) continue; + this.resources.add((Object)ResourceInfo.of(entry.getName(), classloader)); + } + } + finally { + try { + jarFile.close(); + } + catch (IOException ignored) {} + } + } + + @VisibleForTesting + static ImmutableSet getClassPathFromManifest(File jarFile, @Nullable Manifest manifest) { + if (manifest == null) { + return ImmutableSet.of(); + } + ImmutableSet.Builder builder = ImmutableSet.builder(); + String classpathAttribute = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH.toString()); + if (classpathAttribute != null) { + for (String path : CLASS_PATH_ATTRIBUTE_SEPARATOR.split(classpathAttribute)) { + URI uri; + try { + uri = Scanner.getClassPathEntry(jarFile, path); + } + catch (URISyntaxException e) { + String string = String.valueOf(path); + logger.warning(string.length() != 0 ? "Invalid Class-Path entry: ".concat(string) : new String("Invalid Class-Path entry: ")); + continue; + } + builder.add(uri); + } + } + return builder.build(); + } + + @VisibleForTesting + static URI getClassPathEntry(File jarFile, String path) throws URISyntaxException { + URI uri = new URI(path); + if (uri.isAbsolute()) { + return uri; + } + return new File(jarFile.getParentFile(), path.replace('/', File.separatorChar)).toURI(); + } + } + + @Beta + public static final class ClassInfo + extends ResourceInfo { + private final String className; + + ClassInfo(String resourceName, ClassLoader loader) { + super(resourceName, loader); + this.className = ClassPath.getClassName(resourceName); + } + + public String getPackageName() { + return Reflection.getPackageName(this.className); + } + + public String getSimpleName() { + int lastDollarSign = this.className.lastIndexOf(36); + if (lastDollarSign != -1) { + String innerClassName = this.className.substring(lastDollarSign + 1); + return CharMatcher.DIGIT.trimLeadingFrom(innerClassName); + } + String packageName = this.getPackageName(); + if (packageName.isEmpty()) { + return this.className; + } + return this.className.substring(packageName.length() + 1); + } + + public String getName() { + return this.className; + } + + public Class load() { + try { + return this.loader.loadClass(this.className); + } + catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } + + @Override + public String toString() { + return this.className; + } + } + + @Beta + public static class ResourceInfo { + private final String resourceName; + final ClassLoader loader; + + static ResourceInfo of(String resourceName, ClassLoader loader) { + if (resourceName.endsWith(ClassPath.CLASS_FILE_NAME_EXTENSION)) { + return new ClassInfo(resourceName, loader); + } + return new ResourceInfo(resourceName, loader); + } + + ResourceInfo(String resourceName, ClassLoader loader) { + this.resourceName = Preconditions.checkNotNull(resourceName); + this.loader = Preconditions.checkNotNull(loader); + } + + public final URL url() { + return Preconditions.checkNotNull(this.loader.getResource(this.resourceName), "Failed to load resource: %s", this.resourceName); + } + + public final String getResourceName() { + return this.resourceName; + } + + public int hashCode() { + return this.resourceName.hashCode(); + } + + public boolean equals(Object obj) { + if (obj instanceof ResourceInfo) { + ResourceInfo that = (ResourceInfo)obj; + return this.resourceName.equals(that.resourceName) && this.loader == that.loader; + } + return false; + } + + public String toString() { + return this.resourceName; + } + } +} diff --git a/src/com/google/common/reflect/Element.java b/src/com/google/common/reflect/Element.java new file mode 100644 index 0000000..f60d49f --- /dev/null +++ b/src/com/google/common/reflect/Element.java @@ -0,0 +1,138 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.base.Preconditions; +import com.google.common.reflect.TypeToken; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; +import javax.annotation.Nullable; + +class Element +extends AccessibleObject +implements Member { + private final AccessibleObject accessibleObject; + private final Member member; + + Element(M member) { + Preconditions.checkNotNull(member); + this.accessibleObject = member; + this.member = (Member)((Object)member); + } + + public TypeToken getOwnerType() { + return TypeToken.of(this.getDeclaringClass()); + } + + @Override + public final boolean isAnnotationPresent(Class annotationClass) { + return this.accessibleObject.isAnnotationPresent(annotationClass); + } + + public final A getAnnotation(Class annotationClass) { + return this.accessibleObject.getAnnotation(annotationClass); + } + + @Override + public final Annotation[] getAnnotations() { + return this.accessibleObject.getAnnotations(); + } + + @Override + public final Annotation[] getDeclaredAnnotations() { + return this.accessibleObject.getDeclaredAnnotations(); + } + + @Override + public final void setAccessible(boolean flag) throws SecurityException { + this.accessibleObject.setAccessible(flag); + } + + @Override + public final boolean isAccessible() { + return this.accessibleObject.isAccessible(); + } + + @Override + public Class getDeclaringClass() { + return this.member.getDeclaringClass(); + } + + @Override + public final String getName() { + return this.member.getName(); + } + + @Override + public final int getModifiers() { + return this.member.getModifiers(); + } + + @Override + public final boolean isSynthetic() { + return this.member.isSynthetic(); + } + + public final boolean isPublic() { + return Modifier.isPublic(this.getModifiers()); + } + + public final boolean isProtected() { + return Modifier.isProtected(this.getModifiers()); + } + + public final boolean isPackagePrivate() { + return !this.isPrivate() && !this.isPublic() && !this.isProtected(); + } + + public final boolean isPrivate() { + return Modifier.isPrivate(this.getModifiers()); + } + + public final boolean isStatic() { + return Modifier.isStatic(this.getModifiers()); + } + + public final boolean isFinal() { + return Modifier.isFinal(this.getModifiers()); + } + + public final boolean isAbstract() { + return Modifier.isAbstract(this.getModifiers()); + } + + public final boolean isNative() { + return Modifier.isNative(this.getModifiers()); + } + + public final boolean isSynchronized() { + return Modifier.isSynchronized(this.getModifiers()); + } + + final boolean isVolatile() { + return Modifier.isVolatile(this.getModifiers()); + } + + final boolean isTransient() { + return Modifier.isTransient(this.getModifiers()); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof Element) { + Element that = (Element)obj; + return this.getOwnerType().equals(that.getOwnerType()) && this.member.equals(that.member); + } + return false; + } + + public int hashCode() { + return this.member.hashCode(); + } + + public String toString() { + return this.member.toString(); + } +} diff --git a/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java b/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java new file mode 100644 index 0000000..d9bb64b --- /dev/null +++ b/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToInstanceMap; +import com.google.common.reflect.TypeToken; +import java.util.Map; + +@Beta +public final class ImmutableTypeToInstanceMap +extends ForwardingMap, B> +implements TypeToInstanceMap { + private final ImmutableMap, B> delegate; + + public static ImmutableTypeToInstanceMap of() { + return new ImmutableTypeToInstanceMap(ImmutableMap.of()); + } + + public static Builder builder() { + return new Builder(); + } + + private ImmutableTypeToInstanceMap(ImmutableMap, B> delegate) { + this.delegate = delegate; + } + + @Override + public T getInstance(TypeToken type) { + return this.trustedGet(type.rejectTypeVariables()); + } + + @Override + public T putInstance(TypeToken type, T value) { + throw new UnsupportedOperationException(); + } + + @Override + public T getInstance(Class type) { + return this.trustedGet(TypeToken.of(type)); + } + + @Override + public T putInstance(Class type, T value) { + throw new UnsupportedOperationException(); + } + + @Override + protected Map, B> delegate() { + return this.delegate; + } + + private T trustedGet(TypeToken type) { + return (T)this.delegate.get(type); + } + + @Beta + public static final class Builder { + private final ImmutableMap.Builder, B> mapBuilder = ImmutableMap.builder(); + + private Builder() { + } + + public Builder put(Class key, T value) { + this.mapBuilder.put(TypeToken.of(key), value); + return this; + } + + public Builder put(TypeToken key, T value) { + this.mapBuilder.put(key.rejectTypeVariables(), value); + return this; + } + + public ImmutableTypeToInstanceMap build() { + return new ImmutableTypeToInstanceMap(this.mapBuilder.build()); + } + } +} diff --git a/src/com/google/common/reflect/Invokable.java b/src/com/google/common/reflect/Invokable.java new file mode 100644 index 0000000..754253e --- /dev/null +++ b/src/com/google/common/reflect/Invokable.java @@ -0,0 +1,236 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.Element; +import com.google.common.reflect.Parameter; +import com.google.common.reflect.TypeToken; +import com.google.common.reflect.Types; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import javax.annotation.Nullable; + +@Beta +public abstract class Invokable +extends Element +implements GenericDeclaration { + Invokable(M member) { + super(member); + } + + public static Invokable from(Method method) { + return new MethodInvokable(method); + } + + public static Invokable from(Constructor constructor) { + return new ConstructorInvokable(constructor); + } + + public abstract boolean isOverridable(); + + public abstract boolean isVarArgs(); + + public final R invoke(@Nullable T receiver, Object ... args) throws InvocationTargetException, IllegalAccessException { + return (R)this.invokeInternal(receiver, Preconditions.checkNotNull(args)); + } + + public final TypeToken getReturnType() { + return TypeToken.of(this.getGenericReturnType()); + } + + public final ImmutableList getParameters() { + Type[] parameterTypes = this.getGenericParameterTypes(); + Annotation[][] annotations = this.getParameterAnnotations(); + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < parameterTypes.length; ++i) { + builder.add(new Parameter(this, i, TypeToken.of(parameterTypes[i]), annotations[i])); + } + return builder.build(); + } + + public final ImmutableList> getExceptionTypes() { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Type type : this.getGenericExceptionTypes()) { + TypeToken exceptionType = TypeToken.of(type); + builder.add(exceptionType); + } + return builder.build(); + } + + public final Invokable returning(Class returnType) { + return this.returning(TypeToken.of(returnType)); + } + + public final Invokable returning(TypeToken returnType) { + if (!returnType.isAssignableFrom(this.getReturnType())) { + String string = String.valueOf(String.valueOf(this.getReturnType())); + String string2 = String.valueOf(String.valueOf(returnType)); + throw new IllegalArgumentException(new StringBuilder(35 + string.length() + string2.length()).append("Invokable is known to return ").append(string).append(", not ").append(string2).toString()); + } + Invokable specialized = this; + return specialized; + } + + public final Class getDeclaringClass() { + return super.getDeclaringClass(); + } + + public TypeToken getOwnerType() { + return TypeToken.of(this.getDeclaringClass()); + } + + abstract Object invokeInternal(@Nullable Object var1, Object[] var2) throws InvocationTargetException, IllegalAccessException; + + abstract Type[] getGenericParameterTypes(); + + abstract Type[] getGenericExceptionTypes(); + + abstract Annotation[][] getParameterAnnotations(); + + abstract Type getGenericReturnType(); + + static class ConstructorInvokable + extends Invokable { + final Constructor constructor; + + ConstructorInvokable(Constructor constructor) { + super(constructor); + this.constructor = constructor; + } + + @Override + final Object invokeInternal(@Nullable Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException { + try { + return this.constructor.newInstance(args); + } + catch (InstantiationException e) { + String string = String.valueOf(String.valueOf(this.constructor)); + throw new RuntimeException(new StringBuilder(8 + string.length()).append(string).append(" failed.").toString(), e); + } + } + + @Override + Type getGenericReturnType() { + Class declaringClass = this.getDeclaringClass(); + Type[] typeParams = declaringClass.getTypeParameters(); + if (typeParams.length > 0) { + return Types.newParameterizedType(declaringClass, typeParams); + } + return declaringClass; + } + + @Override + Type[] getGenericParameterTypes() { + Class[] rawParamTypes; + Type[] types = this.constructor.getGenericParameterTypes(); + if (types.length > 0 && this.mayNeedHiddenThis() && types.length == (rawParamTypes = this.constructor.getParameterTypes()).length && rawParamTypes[0] == this.getDeclaringClass().getEnclosingClass()) { + return Arrays.copyOfRange(types, 1, types.length); + } + return types; + } + + @Override + Type[] getGenericExceptionTypes() { + return this.constructor.getGenericExceptionTypes(); + } + + @Override + final Annotation[][] getParameterAnnotations() { + return this.constructor.getParameterAnnotations(); + } + + @Override + public final TypeVariable[] getTypeParameters() { + TypeVariable>[] declaredByClass = this.getDeclaringClass().getTypeParameters(); + TypeVariable>[] declaredByConstructor = this.constructor.getTypeParameters(); + TypeVariable[] result = new TypeVariable[declaredByClass.length + declaredByConstructor.length]; + System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length); + System.arraycopy(declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length); + return result; + } + + @Override + public final boolean isOverridable() { + return false; + } + + @Override + public final boolean isVarArgs() { + return this.constructor.isVarArgs(); + } + + private boolean mayNeedHiddenThis() { + Class declaringClass = this.constructor.getDeclaringClass(); + if (declaringClass.getEnclosingConstructor() != null) { + return true; + } + Method enclosingMethod = declaringClass.getEnclosingMethod(); + if (enclosingMethod != null) { + return !Modifier.isStatic(enclosingMethod.getModifiers()); + } + return declaringClass.getEnclosingClass() != null && !Modifier.isStatic(declaringClass.getModifiers()); + } + } + + static class MethodInvokable + extends Invokable { + final Method method; + + MethodInvokable(Method method) { + super(method); + this.method = method; + } + + @Override + final Object invokeInternal(@Nullable Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException { + return this.method.invoke(receiver, args); + } + + @Override + Type getGenericReturnType() { + return this.method.getGenericReturnType(); + } + + @Override + Type[] getGenericParameterTypes() { + return this.method.getGenericParameterTypes(); + } + + @Override + Type[] getGenericExceptionTypes() { + return this.method.getGenericExceptionTypes(); + } + + @Override + final Annotation[][] getParameterAnnotations() { + return this.method.getParameterAnnotations(); + } + + @Override + public final TypeVariable[] getTypeParameters() { + return this.method.getTypeParameters(); + } + + @Override + public final boolean isOverridable() { + return !this.isFinal() && !this.isPrivate() && !this.isStatic() && !Modifier.isFinal(this.getDeclaringClass().getModifiers()); + } + + @Override + public final boolean isVarArgs() { + return this.method.isVarArgs(); + } + } +} diff --git a/src/com/google/common/reflect/MutableTypeToInstanceMap.java b/src/com/google/common/reflect/MutableTypeToInstanceMap.java new file mode 100644 index 0000000..a78ce12 --- /dev/null +++ b/src/com/google/common/reflect/MutableTypeToInstanceMap.java @@ -0,0 +1,134 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.reflect.TypeToInstanceMap; +import com.google.common.reflect.TypeToken; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +public final class MutableTypeToInstanceMap +extends ForwardingMap, B> +implements TypeToInstanceMap { + private final Map, B> backingMap = Maps.newHashMap(); + + @Override + @Nullable + public T getInstance(Class type) { + return this.trustedGet(TypeToken.of(type)); + } + + @Override + @Nullable + public T putInstance(Class type, @Nullable T value) { + return this.trustedPut(TypeToken.of(type), value); + } + + @Override + @Nullable + public T getInstance(TypeToken type) { + return this.trustedGet(type.rejectTypeVariables()); + } + + @Override + @Nullable + public T putInstance(TypeToken type, @Nullable T value) { + return this.trustedPut(type.rejectTypeVariables(), value); + } + + @Override + public B put(TypeToken key, B value) { + throw new UnsupportedOperationException("Please use putInstance() instead."); + } + + @Override + public void putAll(Map, ? extends B> map) { + throw new UnsupportedOperationException("Please use putInstance() instead."); + } + + @Override + public Set, B>> entrySet() { + return UnmodifiableEntry.transformEntries(super.entrySet()); + } + + @Override + protected Map, B> delegate() { + return this.backingMap; + } + + @Nullable + private T trustedPut(TypeToken type, @Nullable T value) { + return (T)this.backingMap.put(type, value); + } + + @Nullable + private T trustedGet(TypeToken type) { + return (T)this.backingMap.get(type); + } + + private static final class UnmodifiableEntry + extends ForwardingMapEntry { + private final Map.Entry delegate; + + static Set> transformEntries(final Set> entries) { + return new ForwardingSet>(){ + + @Override + protected Set> delegate() { + return entries; + } + + @Override + public Iterator> iterator() { + return UnmodifiableEntry.transformEntries(super.iterator()); + } + + @Override + public Object[] toArray() { + return this.standardToArray(); + } + + @Override + public T[] toArray(T[] array) { + return this.standardToArray(array); + } + }; + } + + private static Iterator> transformEntries(Iterator> entries) { + return Iterators.transform(entries, new Function, Map.Entry>(){ + + @Override + public Map.Entry apply(Map.Entry entry) { + return new UnmodifiableEntry(entry); + } + }); + } + + private UnmodifiableEntry(Map.Entry delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected Map.Entry delegate() { + return this.delegate; + } + + @Override + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/com/google/common/reflect/Parameter.java b/src/com/google/common/reflect/Parameter.java new file mode 100644 index 0000000..0228c29 --- /dev/null +++ b/src/com/google/common/reflect/Parameter.java @@ -0,0 +1,95 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; +import com.google.common.reflect.Invokable; +import com.google.common.reflect.TypeToken; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import javax.annotation.Nullable; + +@Beta +public final class Parameter +implements AnnotatedElement { + private final Invokable declaration; + private final int position; + private final TypeToken type; + private final ImmutableList annotations; + + Parameter(Invokable declaration, int position, TypeToken type, Annotation[] annotations) { + this.declaration = declaration; + this.position = position; + this.type = type; + this.annotations = ImmutableList.copyOf(annotations); + } + + public TypeToken getType() { + return this.type; + } + + public Invokable getDeclaringInvokable() { + return this.declaration; + } + + @Override + public boolean isAnnotationPresent(Class annotationType) { + return this.getAnnotation((Class)annotationType) != null; + } + + @Nullable + public A getAnnotation(Class annotationType) { + Preconditions.checkNotNull(annotationType); + for (Annotation annotation : this.annotations) { + if (!annotationType.isInstance(annotation)) continue; + return (A)((Annotation)annotationType.cast(annotation)); + } + return null; + } + + @Override + public Annotation[] getAnnotations() { + return this.getDeclaredAnnotations(); + } + + public A[] getAnnotationsByType(Class annotationType) { + return this.getDeclaredAnnotationsByType(annotationType); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return this.annotations.toArray(new Annotation[this.annotations.size()]); + } + + @Nullable + public A getDeclaredAnnotation(Class annotationType) { + Preconditions.checkNotNull(annotationType); + return (A)((Annotation)FluentIterable.from(this.annotations).filter(annotationType).first().orNull()); + } + + public A[] getDeclaredAnnotationsByType(Class annotationType) { + return (Annotation[])FluentIterable.from(this.annotations).filter(annotationType).toArray(annotationType); + } + + public boolean equals(@Nullable Object obj) { + if (obj instanceof Parameter) { + Parameter that = (Parameter)obj; + return this.position == that.position && this.declaration.equals(that.declaration); + } + return false; + } + + public int hashCode() { + return this.position; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.type)); + int n = this.position; + return new StringBuilder(15 + string.length()).append(string).append(" arg").append(n).toString(); + } +} diff --git a/src/com/google/common/reflect/Reflection.java b/src/com/google/common/reflect/Reflection.java new file mode 100644 index 0000000..75d3d5a --- /dev/null +++ b/src/com/google/common/reflect/Reflection.java @@ -0,0 +1,42 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +@Beta +public final class Reflection { + public static String getPackageName(Class clazz) { + return Reflection.getPackageName(clazz.getName()); + } + + public static String getPackageName(String classFullName) { + int lastDot = classFullName.lastIndexOf(46); + return lastDot < 0 ? "" : classFullName.substring(0, lastDot); + } + + public static void initialize(Class ... classes) { + for (Class clazz : classes) { + try { + Class.forName(clazz.getName(), true, clazz.getClassLoader()); + } + catch (ClassNotFoundException e) { + throw new AssertionError((Object)e); + } + } + } + + public static T newProxy(Class interfaceType, InvocationHandler handler) { + Preconditions.checkNotNull(handler); + Preconditions.checkArgument(interfaceType.isInterface(), "%s is not an interface", interfaceType); + Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[]{interfaceType}, handler); + return interfaceType.cast(object); + } + + private Reflection() { + } +} diff --git a/src/com/google/common/reflect/TypeCapture.java b/src/com/google/common/reflect/TypeCapture.java new file mode 100644 index 0000000..b1c5eb6 --- /dev/null +++ b/src/com/google/common/reflect/TypeCapture.java @@ -0,0 +1,19 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.base.Preconditions; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +abstract class TypeCapture { + TypeCapture() { + } + + final Type capture() { + Type superclass = this.getClass().getGenericSuperclass(); + Preconditions.checkArgument(superclass instanceof ParameterizedType, "%s isn't parameterized", superclass); + return ((ParameterizedType)superclass).getActualTypeArguments()[0]; + } +} diff --git a/src/com/google/common/reflect/TypeParameter.java b/src/com/google/common/reflect/TypeParameter.java new file mode 100644 index 0000000..0bcaba3 --- /dev/null +++ b/src/com/google/common/reflect/TypeParameter.java @@ -0,0 +1,39 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.reflect.TypeCapture; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import javax.annotation.Nullable; + +@Beta +public abstract class TypeParameter +extends TypeCapture { + final TypeVariable typeVariable; + + protected TypeParameter() { + Type type = this.capture(); + Preconditions.checkArgument(type instanceof TypeVariable, "%s should be a type variable.", type); + this.typeVariable = (TypeVariable)type; + } + + public final int hashCode() { + return this.typeVariable.hashCode(); + } + + public final boolean equals(@Nullable Object o) { + if (o instanceof TypeParameter) { + TypeParameter that = (TypeParameter)o; + return this.typeVariable.equals(that.typeVariable); + } + return false; + } + + public String toString() { + return this.typeVariable.toString(); + } +} diff --git a/src/com/google/common/reflect/TypeResolver.java b/src/com/google/common/reflect/TypeResolver.java new file mode 100644 index 0000000..61d6ca0 --- /dev/null +++ b/src/com/google/common/reflect/TypeResolver.java @@ -0,0 +1,374 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.reflect.TypeVisitor; +import com.google.common.reflect.Types; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + +@Beta +public final class TypeResolver { + private final TypeTable typeTable; + + public TypeResolver() { + this.typeTable = new TypeTable(); + } + + private TypeResolver(TypeTable typeTable) { + this.typeTable = typeTable; + } + + static TypeResolver accordingTo(Type type) { + return new TypeResolver().where(TypeMappingIntrospector.getTypeMappings(type)); + } + + public TypeResolver where(Type formal, Type actual) { + HashMap mappings = Maps.newHashMap(); + TypeResolver.populateTypeMappings(mappings, Preconditions.checkNotNull(formal), Preconditions.checkNotNull(actual)); + return this.where(mappings); + } + + TypeResolver where(Map mappings) { + return new TypeResolver(this.typeTable.where(mappings)); + } + + private static void populateTypeMappings(final Map mappings, Type from, final Type to) { + if (from.equals(to)) { + return; + } + new TypeVisitor(){ + + @Override + void visitTypeVariable(TypeVariable typeVariable) { + mappings.put(new TypeVariableKey(typeVariable), to); + } + + @Override + void visitWildcardType(WildcardType fromWildcardType) { + int i; + WildcardType toWildcardType = (WildcardType)TypeResolver.expectArgument(WildcardType.class, to); + Type[] fromUpperBounds = fromWildcardType.getUpperBounds(); + Type[] toUpperBounds = toWildcardType.getUpperBounds(); + Type[] fromLowerBounds = fromWildcardType.getLowerBounds(); + Type[] toLowerBounds = toWildcardType.getLowerBounds(); + Preconditions.checkArgument(fromUpperBounds.length == toUpperBounds.length && fromLowerBounds.length == toLowerBounds.length, "Incompatible type: %s vs. %s", fromWildcardType, to); + for (i = 0; i < fromUpperBounds.length; ++i) { + TypeResolver.populateTypeMappings(mappings, fromUpperBounds[i], toUpperBounds[i]); + } + for (i = 0; i < fromLowerBounds.length; ++i) { + TypeResolver.populateTypeMappings(mappings, fromLowerBounds[i], toLowerBounds[i]); + } + } + + @Override + void visitParameterizedType(ParameterizedType fromParameterizedType) { + ParameterizedType toParameterizedType = (ParameterizedType)TypeResolver.expectArgument(ParameterizedType.class, to); + Preconditions.checkArgument(fromParameterizedType.getRawType().equals(toParameterizedType.getRawType()), "Inconsistent raw type: %s vs. %s", fromParameterizedType, to); + Type[] fromArgs = fromParameterizedType.getActualTypeArguments(); + Type[] toArgs = toParameterizedType.getActualTypeArguments(); + Preconditions.checkArgument(fromArgs.length == toArgs.length, "%s not compatible with %s", fromParameterizedType, toParameterizedType); + for (int i = 0; i < fromArgs.length; ++i) { + TypeResolver.populateTypeMappings(mappings, fromArgs[i], toArgs[i]); + } + } + + @Override + void visitGenericArrayType(GenericArrayType fromArrayType) { + Type componentType = Types.getComponentType(to); + Preconditions.checkArgument(componentType != null, "%s is not an array type.", to); + TypeResolver.populateTypeMappings(mappings, fromArrayType.getGenericComponentType(), componentType); + } + + @Override + void visitClass(Class fromClass) { + String string = String.valueOf(String.valueOf(fromClass)); + throw new IllegalArgumentException(new StringBuilder(21 + string.length()).append("No type mapping from ").append(string).toString()); + } + }.visit(from); + } + + public Type resolveType(Type type) { + Preconditions.checkNotNull(type); + if (type instanceof TypeVariable) { + return this.typeTable.resolve((TypeVariable)type); + } + if (type instanceof ParameterizedType) { + return this.resolveParameterizedType((ParameterizedType)type); + } + if (type instanceof GenericArrayType) { + return this.resolveGenericArrayType((GenericArrayType)type); + } + if (type instanceof WildcardType) { + return this.resolveWildcardType((WildcardType)type); + } + return type; + } + + private Type[] resolveTypes(Type[] types) { + Type[] result = new Type[types.length]; + for (int i = 0; i < types.length; ++i) { + result[i] = this.resolveType(types[i]); + } + return result; + } + + private WildcardType resolveWildcardType(WildcardType type) { + Type[] lowerBounds = type.getLowerBounds(); + Type[] upperBounds = type.getUpperBounds(); + return new Types.WildcardTypeImpl(this.resolveTypes(lowerBounds), this.resolveTypes(upperBounds)); + } + + private Type resolveGenericArrayType(GenericArrayType type) { + Type componentType = type.getGenericComponentType(); + Type resolvedComponentType = this.resolveType(componentType); + return Types.newArrayType(resolvedComponentType); + } + + private ParameterizedType resolveParameterizedType(ParameterizedType type) { + Type owner = type.getOwnerType(); + Type resolvedOwner = owner == null ? null : this.resolveType(owner); + Type resolvedRawType = this.resolveType(type.getRawType()); + Type[] args = type.getActualTypeArguments(); + Type[] resolvedArgs = this.resolveTypes(args); + return Types.newParameterizedTypeWithOwner(resolvedOwner, (Class)resolvedRawType, resolvedArgs); + } + + private static T expectArgument(Class type, Object arg) { + try { + return type.cast(arg); + } + catch (ClassCastException e) { + String string = String.valueOf(String.valueOf(arg)); + String string2 = String.valueOf(String.valueOf(type.getSimpleName())); + throw new IllegalArgumentException(new StringBuilder(10 + string.length() + string2.length()).append(string).append(" is not a ").append(string2).toString()); + } + } + + static final class TypeVariableKey { + private final TypeVariable var; + + TypeVariableKey(TypeVariable var) { + this.var = Preconditions.checkNotNull(var); + } + + public int hashCode() { + return Objects.hashCode(this.var.getGenericDeclaration(), this.var.getName()); + } + + public boolean equals(Object obj) { + if (obj instanceof TypeVariableKey) { + TypeVariableKey that = (TypeVariableKey)obj; + return this.equalsTypeVariable(that.var); + } + return false; + } + + public String toString() { + return this.var.toString(); + } + + static Object forLookup(Type t) { + if (t instanceof TypeVariable) { + return new TypeVariableKey((TypeVariable)t); + } + return null; + } + + boolean equalsType(Type type) { + if (type instanceof TypeVariable) { + return this.equalsTypeVariable((TypeVariable)type); + } + return false; + } + + private boolean equalsTypeVariable(TypeVariable that) { + return this.var.getGenericDeclaration().equals(that.getGenericDeclaration()) && this.var.getName().equals(that.getName()); + } + } + + private static final class WildcardCapturer { + private final AtomicInteger id = new AtomicInteger(); + + private WildcardCapturer() { + } + + Type capture(Type type) { + Preconditions.checkNotNull(type); + if (type instanceof Class) { + return type; + } + if (type instanceof TypeVariable) { + return type; + } + if (type instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType)type; + return Types.newArrayType(this.capture(arrayType.getGenericComponentType())); + } + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType)type; + return Types.newParameterizedTypeWithOwner(this.captureNullable(parameterizedType.getOwnerType()), (Class)parameterizedType.getRawType(), this.capture(parameterizedType.getActualTypeArguments())); + } + if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType)type; + Type[] lowerBounds = wildcardType.getLowerBounds(); + if (lowerBounds.length == 0) { + Object[] upperBounds = wildcardType.getUpperBounds(); + int n = this.id.incrementAndGet(); + String string = String.valueOf(String.valueOf(Joiner.on('&').join(upperBounds))); + String name = new StringBuilder(33 + string.length()).append("capture#").append(n).append("-of ? extends ").append(string).toString(); + return Types.newArtificialTypeVariable(WildcardCapturer.class, name, wildcardType.getUpperBounds()); + } + return type; + } + throw new AssertionError((Object)"must have been one of the known types"); + } + + private Type captureNullable(@Nullable Type type) { + if (type == null) { + return null; + } + return this.capture(type); + } + + private Type[] capture(Type[] types) { + Type[] result = new Type[types.length]; + for (int i = 0; i < types.length; ++i) { + result[i] = this.capture(types[i]); + } + return result; + } + } + + private static final class TypeMappingIntrospector + extends TypeVisitor { + private static final WildcardCapturer wildcardCapturer = new WildcardCapturer(); + private final Map mappings = Maps.newHashMap(); + + private TypeMappingIntrospector() { + } + + static ImmutableMap getTypeMappings(Type contextType) { + TypeMappingIntrospector introspector = new TypeMappingIntrospector(); + introspector.visit(wildcardCapturer.capture(contextType)); + return ImmutableMap.copyOf(introspector.mappings); + } + + @Override + void visitClass(Class clazz) { + this.visit(clazz.getGenericSuperclass()); + this.visit(clazz.getGenericInterfaces()); + } + + @Override + void visitParameterizedType(ParameterizedType parameterizedType) { + Type[] typeArgs; + Class rawClass = (Class)parameterizedType.getRawType(); + TypeVariable>[] vars = rawClass.getTypeParameters(); + Preconditions.checkState(vars.length == (typeArgs = parameterizedType.getActualTypeArguments()).length); + for (int i = 0; i < vars.length; ++i) { + this.map(new TypeVariableKey(vars[i]), typeArgs[i]); + } + this.visit(rawClass); + this.visit(parameterizedType.getOwnerType()); + } + + @Override + void visitTypeVariable(TypeVariable t) { + this.visit(t.getBounds()); + } + + @Override + void visitWildcardType(WildcardType t) { + this.visit(t.getUpperBounds()); + } + + private void map(TypeVariableKey var, Type arg) { + if (this.mappings.containsKey(var)) { + return; + } + Type t = arg; + while (t != null) { + if (var.equalsType(t)) { + Type x = arg; + while (x != null) { + x = this.mappings.remove(TypeVariableKey.forLookup(x)); + } + return; + } + t = this.mappings.get(TypeVariableKey.forLookup(t)); + } + this.mappings.put(var, arg); + } + } + + private static class TypeTable { + private final ImmutableMap map; + + TypeTable() { + this.map = ImmutableMap.of(); + } + + private TypeTable(ImmutableMap map) { + this.map = map; + } + + final TypeTable where(Map mappings) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(this.map); + for (Map.Entry mapping : mappings.entrySet()) { + Type type; + TypeVariableKey variable = mapping.getKey(); + Preconditions.checkArgument(!variable.equalsType(type = mapping.getValue()), "Type variable %s bound to itself", variable); + builder.put(variable, type); + } + return new TypeTable(builder.build()); + } + + final Type resolve(final TypeVariable var) { + final TypeTable unguarded = this; + TypeTable guarded = new TypeTable(){ + + @Override + public Type resolveInternal(TypeVariable intermediateVar, TypeTable forDependent) { + if (intermediateVar.getGenericDeclaration().equals(var.getGenericDeclaration())) { + return intermediateVar; + } + return unguarded.resolveInternal(intermediateVar, forDependent); + } + }; + return this.resolveInternal(var, guarded); + } + + Type resolveInternal(TypeVariable var, TypeTable forDependants) { + Type type = this.map.get(new TypeVariableKey(var)); + if (type == null) { + Object[] bounds = var.getBounds(); + if (bounds.length == 0) { + return var; + } + Object[] resolvedBounds = new TypeResolver(forDependants).resolveTypes((Type[])bounds); + if (Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY && Arrays.equals(bounds, resolvedBounds)) { + return var; + } + return Types.newArtificialTypeVariable(var.getGenericDeclaration(), var.getName(), (Type[])resolvedBounds); + } + return new TypeResolver(forDependants).resolveType(type); + } + } +} diff --git a/src/com/google/common/reflect/TypeToInstanceMap.java b/src/com/google/common/reflect/TypeToInstanceMap.java new file mode 100644 index 0000000..5f2b5a3 --- /dev/null +++ b/src/com/google/common/reflect/TypeToInstanceMap.java @@ -0,0 +1,25 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.reflect.TypeToken; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +public interface TypeToInstanceMap +extends Map, B> { + @Nullable + public T getInstance(Class var1); + + @Nullable + public T putInstance(Class var1, @Nullable T var2); + + @Nullable + public T getInstance(TypeToken var1); + + @Nullable + public T putInstance(TypeToken var1, @Nullable T var2); +} diff --git a/src/com/google/common/reflect/TypeToken.java b/src/com/google/common/reflect/TypeToken.java new file mode 100644 index 0000000..3a3b94a --- /dev/null +++ b/src/com/google/common/reflect/TypeToken.java @@ -0,0 +1,898 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.primitives.Primitives; +import com.google.common.reflect.Invokable; +import com.google.common.reflect.TypeCapture; +import com.google.common.reflect.TypeParameter; +import com.google.common.reflect.TypeResolver; +import com.google.common.reflect.TypeVisitor; +import com.google.common.reflect.Types; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +public abstract class TypeToken +extends TypeCapture +implements Serializable { + private final Type runtimeType; + private transient TypeResolver typeResolver; + + protected TypeToken() { + this.runtimeType = this.capture(); + Preconditions.checkState(!(this.runtimeType instanceof TypeVariable), "Cannot construct a TypeToken for a type variable.\nYou probably meant to call new TypeToken<%s>(getClass()) that can resolve the type variable for you.\nIf you do need to create a TypeToken of a type variable, please use TypeToken.of() instead.", this.runtimeType); + } + + protected TypeToken(Class declaringClass) { + Type captured = super.capture(); + this.runtimeType = captured instanceof Class ? captured : TypeToken.of(declaringClass).resolveType((Type)captured).runtimeType; + } + + private TypeToken(Type type) { + this.runtimeType = Preconditions.checkNotNull(type); + } + + public static TypeToken of(Class type) { + return new SimpleTypeToken((Type)type); + } + + public static TypeToken of(Type type) { + return new SimpleTypeToken(type); + } + + public final Class getRawType() { + Class rawType; + Class result = rawType = TypeToken.getRawType(this.runtimeType); + return result; + } + + private ImmutableSet> getImmediateRawTypes() { + ImmutableSet> result = TypeToken.getRawTypes(this.runtimeType); + return result; + } + + public final Type getType() { + return this.runtimeType; + } + + public final TypeToken where(TypeParameter typeParam, TypeToken typeArg) { + TypeResolver resolver = new TypeResolver().where(ImmutableMap.of(new TypeResolver.TypeVariableKey(typeParam.typeVariable), typeArg.runtimeType)); + return new SimpleTypeToken(resolver.resolveType(this.runtimeType)); + } + + public final TypeToken where(TypeParameter typeParam, Class typeArg) { + return this.where(typeParam, TypeToken.of(typeArg)); + } + + public final TypeToken resolveType(Type type) { + Preconditions.checkNotNull(type); + TypeResolver resolver = this.typeResolver; + if (resolver == null) { + resolver = this.typeResolver = TypeResolver.accordingTo(this.runtimeType); + } + return TypeToken.of(resolver.resolveType(type)); + } + + private Type[] resolveInPlace(Type[] types) { + for (int i = 0; i < types.length; ++i) { + types[i] = this.resolveType(types[i]).getType(); + } + return types; + } + + private TypeToken resolveSupertype(Type type) { + TypeToken supertype = this.resolveType(type); + supertype.typeResolver = this.typeResolver; + return supertype; + } + + @Nullable + final TypeToken getGenericSuperclass() { + if (this.runtimeType instanceof TypeVariable) { + return this.boundAsSuperclass(((TypeVariable)this.runtimeType).getBounds()[0]); + } + if (this.runtimeType instanceof WildcardType) { + return this.boundAsSuperclass(((WildcardType)this.runtimeType).getUpperBounds()[0]); + } + Type superclass = this.getRawType().getGenericSuperclass(); + if (superclass == null) { + return null; + } + TypeToken superToken = this.resolveSupertype(superclass); + return superToken; + } + + @Nullable + private TypeToken boundAsSuperclass(Type bound) { + TypeToken token = TypeToken.of(bound); + if (token.getRawType().isInterface()) { + return null; + } + TypeToken superclass = token; + return superclass; + } + + final ImmutableList> getGenericInterfaces() { + if (this.runtimeType instanceof TypeVariable) { + return this.boundsAsInterfaces(((TypeVariable)this.runtimeType).getBounds()); + } + if (this.runtimeType instanceof WildcardType) { + return this.boundsAsInterfaces(((WildcardType)this.runtimeType).getUpperBounds()); + } + ImmutableList.Builder builder = ImmutableList.builder(); + for (Type interfaceType : this.getRawType().getGenericInterfaces()) { + TypeToken resolvedInterface = this.resolveSupertype(interfaceType); + builder.add(resolvedInterface); + } + return builder.build(); + } + + private ImmutableList> boundsAsInterfaces(Type[] bounds) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Type bound : bounds) { + TypeToken boundType = TypeToken.of(bound); + if (!boundType.getRawType().isInterface()) continue; + builder.add(boundType); + } + return builder.build(); + } + + public final TypeSet getTypes() { + return new TypeSet(); + } + + public final TypeToken getSupertype(Class superclass) { + Preconditions.checkArgument(superclass.isAssignableFrom(this.getRawType()), "%s is not a super class of %s", superclass, this); + if (this.runtimeType instanceof TypeVariable) { + return this.getSupertypeFromUpperBounds(superclass, ((TypeVariable)this.runtimeType).getBounds()); + } + if (this.runtimeType instanceof WildcardType) { + return this.getSupertypeFromUpperBounds(superclass, ((WildcardType)this.runtimeType).getUpperBounds()); + } + if (superclass.isArray()) { + return this.getArraySupertype(superclass); + } + TypeToken supertype = this.resolveSupertype(TypeToken.toGenericType(superclass).runtimeType); + return supertype; + } + + public final TypeToken getSubtype(Class subclass) { + Preconditions.checkArgument(!(this.runtimeType instanceof TypeVariable), "Cannot get subtype of type variable <%s>", this); + if (this.runtimeType instanceof WildcardType) { + return this.getSubtypeFromLowerBounds(subclass, ((WildcardType)this.runtimeType).getLowerBounds()); + } + Preconditions.checkArgument(this.getRawType().isAssignableFrom(subclass), "%s isn't a subclass of %s", subclass, this); + if (this.isArray()) { + return this.getArraySubtype(subclass); + } + TypeToken subtype = TypeToken.of(this.resolveTypeArgsForSubclass(subclass)); + return subtype; + } + + public final boolean isAssignableFrom(TypeToken type) { + return this.isAssignableFrom(type.runtimeType); + } + + public final boolean isAssignableFrom(Type type) { + return TypeToken.isAssignable(Preconditions.checkNotNull(type), this.runtimeType); + } + + public final boolean isArray() { + return this.getComponentType() != null; + } + + public final boolean isPrimitive() { + return this.runtimeType instanceof Class && ((Class)this.runtimeType).isPrimitive(); + } + + public final TypeToken wrap() { + if (this.isPrimitive()) { + Class type = (Class)this.runtimeType; + return TypeToken.of(Primitives.wrap(type)); + } + return this; + } + + private boolean isWrapper() { + return Primitives.allWrapperTypes().contains(this.runtimeType); + } + + public final TypeToken unwrap() { + if (this.isWrapper()) { + Class type = (Class)this.runtimeType; + return TypeToken.of(Primitives.unwrap(type)); + } + return this; + } + + @Nullable + public final TypeToken getComponentType() { + Type componentType = Types.getComponentType(this.runtimeType); + if (componentType == null) { + return null; + } + return TypeToken.of(componentType); + } + + public final Invokable method(Method method) { + Preconditions.checkArgument(TypeToken.of(method.getDeclaringClass()).isAssignableFrom(this), "%s not declared by %s", method, this); + return new Invokable.MethodInvokable(method){ + + @Override + Type getGenericReturnType() { + return TypeToken.this.resolveType(super.getGenericReturnType()).getType(); + } + + @Override + Type[] getGenericParameterTypes() { + return TypeToken.this.resolveInPlace(super.getGenericParameterTypes()); + } + + @Override + Type[] getGenericExceptionTypes() { + return TypeToken.this.resolveInPlace(super.getGenericExceptionTypes()); + } + + @Override + public TypeToken getOwnerType() { + return TypeToken.this; + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.getOwnerType())); + String string2 = String.valueOf(String.valueOf(super.toString())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString(); + } + }; + } + + public final Invokable constructor(Constructor constructor) { + Preconditions.checkArgument(constructor.getDeclaringClass() == this.getRawType(), "%s not declared by %s", constructor, this.getRawType()); + return new Invokable.ConstructorInvokable(constructor){ + + @Override + Type getGenericReturnType() { + return TypeToken.this.resolveType(super.getGenericReturnType()).getType(); + } + + @Override + Type[] getGenericParameterTypes() { + return TypeToken.this.resolveInPlace(super.getGenericParameterTypes()); + } + + @Override + Type[] getGenericExceptionTypes() { + return TypeToken.this.resolveInPlace(super.getGenericExceptionTypes()); + } + + @Override + public TypeToken getOwnerType() { + return TypeToken.this; + } + + @Override + public String toString() { + String string = String.valueOf(String.valueOf(this.getOwnerType())); + String string2 = String.valueOf(String.valueOf(Joiner.on(", ").join(this.getGenericParameterTypes()))); + return new StringBuilder(2 + string.length() + string2.length()).append(string).append("(").append(string2).append(")").toString(); + } + }; + } + + public boolean equals(@Nullable Object o) { + if (o instanceof TypeToken) { + TypeToken that = (TypeToken)o; + return this.runtimeType.equals(that.runtimeType); + } + return false; + } + + public int hashCode() { + return this.runtimeType.hashCode(); + } + + public String toString() { + return Types.toString(this.runtimeType); + } + + protected Object writeReplace() { + return TypeToken.of(new TypeResolver().resolveType(this.runtimeType)); + } + + final TypeToken rejectTypeVariables() { + new TypeVisitor(){ + + @Override + void visitTypeVariable(TypeVariable type) { + String string = String.valueOf(String.valueOf(TypeToken.this.runtimeType)); + throw new IllegalArgumentException(new StringBuilder(58 + string.length()).append(string).append("contains a type variable and is not safe for the operation").toString()); + } + + @Override + void visitWildcardType(WildcardType type) { + this.visit(type.getLowerBounds()); + this.visit(type.getUpperBounds()); + } + + @Override + void visitParameterizedType(ParameterizedType type) { + this.visit(type.getActualTypeArguments()); + this.visit(type.getOwnerType()); + } + + @Override + void visitGenericArrayType(GenericArrayType type) { + this.visit(type.getGenericComponentType()); + } + }.visit(this.runtimeType); + return this; + } + + private static boolean isAssignable(Type from, Type to) { + if (to.equals(from)) { + return true; + } + if (to instanceof WildcardType) { + return TypeToken.isAssignableToWildcardType(from, (WildcardType)to); + } + if (from instanceof TypeVariable) { + return TypeToken.isAssignableFromAny(((TypeVariable)from).getBounds(), to); + } + if (from instanceof WildcardType) { + return TypeToken.isAssignableFromAny(((WildcardType)from).getUpperBounds(), to); + } + if (from instanceof GenericArrayType) { + return TypeToken.isAssignableFromGenericArrayType((GenericArrayType)from, to); + } + if (to instanceof Class) { + return TypeToken.isAssignableToClass(from, (Class)to); + } + if (to instanceof ParameterizedType) { + return TypeToken.isAssignableToParameterizedType(from, (ParameterizedType)to); + } + if (to instanceof GenericArrayType) { + return TypeToken.isAssignableToGenericArrayType(from, (GenericArrayType)to); + } + return false; + } + + private static boolean isAssignableFromAny(Type[] fromTypes, Type to) { + for (Type from : fromTypes) { + if (!TypeToken.isAssignable(from, to)) continue; + return true; + } + return false; + } + + private static boolean isAssignableToClass(Type from, Class to) { + return to.isAssignableFrom(TypeToken.getRawType(from)); + } + + private static boolean isAssignableToWildcardType(Type from, WildcardType to) { + return TypeToken.isAssignable(from, TypeToken.supertypeBound(to)) && TypeToken.isAssignableBySubtypeBound(from, to); + } + + private static boolean isAssignableBySubtypeBound(Type from, WildcardType to) { + Type toSubtypeBound = TypeToken.subtypeBound(to); + if (toSubtypeBound == null) { + return true; + } + Type fromSubtypeBound = TypeToken.subtypeBound(from); + if (fromSubtypeBound == null) { + return false; + } + return TypeToken.isAssignable(toSubtypeBound, fromSubtypeBound); + } + + private static boolean isAssignableToParameterizedType(Type from, ParameterizedType to) { + Class matchedClass = TypeToken.getRawType(to); + if (!matchedClass.isAssignableFrom(TypeToken.getRawType(from))) { + return false; + } + TypeVariable>[] typeParams = matchedClass.getTypeParameters(); + Type[] toTypeArgs = to.getActualTypeArguments(); + TypeToken fromTypeToken = TypeToken.of(from); + for (int i = 0; i < typeParams.length; ++i) { + Type fromTypeArg = fromTypeToken.resolveType(typeParams[i]).runtimeType; + if (TypeToken.matchTypeArgument(fromTypeArg, toTypeArgs[i])) continue; + return false; + } + return true; + } + + private static boolean isAssignableToGenericArrayType(Type from, GenericArrayType to) { + if (from instanceof Class) { + Class fromClass = (Class)from; + if (!fromClass.isArray()) { + return false; + } + return TypeToken.isAssignable(fromClass.getComponentType(), to.getGenericComponentType()); + } + if (from instanceof GenericArrayType) { + GenericArrayType fromArrayType = (GenericArrayType)from; + return TypeToken.isAssignable(fromArrayType.getGenericComponentType(), to.getGenericComponentType()); + } + return false; + } + + private static boolean isAssignableFromGenericArrayType(GenericArrayType from, Type to) { + if (to instanceof Class) { + Class toClass = (Class)to; + if (!toClass.isArray()) { + return toClass == Object.class; + } + return TypeToken.isAssignable(from.getGenericComponentType(), toClass.getComponentType()); + } + if (to instanceof GenericArrayType) { + GenericArrayType toArrayType = (GenericArrayType)to; + return TypeToken.isAssignable(from.getGenericComponentType(), toArrayType.getGenericComponentType()); + } + return false; + } + + private static boolean matchTypeArgument(Type from, Type to) { + if (from.equals(to)) { + return true; + } + if (to instanceof WildcardType) { + return TypeToken.isAssignableToWildcardType(from, (WildcardType)to); + } + return false; + } + + private static Type supertypeBound(Type type) { + if (type instanceof WildcardType) { + return TypeToken.supertypeBound((WildcardType)type); + } + return type; + } + + private static Type supertypeBound(WildcardType type) { + Type[] upperBounds = type.getUpperBounds(); + if (upperBounds.length == 1) { + return TypeToken.supertypeBound(upperBounds[0]); + } + if (upperBounds.length == 0) { + return Object.class; + } + String string = String.valueOf(String.valueOf(type)); + throw new AssertionError((Object)new StringBuilder(59 + string.length()).append("There should be at most one upper bound for wildcard type: ").append(string).toString()); + } + + @Nullable + private static Type subtypeBound(Type type) { + if (type instanceof WildcardType) { + return TypeToken.subtypeBound((WildcardType)type); + } + return type; + } + + @Nullable + private static Type subtypeBound(WildcardType type) { + Type[] lowerBounds = type.getLowerBounds(); + if (lowerBounds.length == 1) { + return TypeToken.subtypeBound(lowerBounds[0]); + } + if (lowerBounds.length == 0) { + return null; + } + String string = String.valueOf(String.valueOf(type)); + throw new AssertionError((Object)new StringBuilder(46 + string.length()).append("Wildcard should have at most one lower bound: ").append(string).toString()); + } + + @VisibleForTesting + static Class getRawType(Type type) { + return (Class)TypeToken.getRawTypes(type).iterator().next(); + } + + @VisibleForTesting + static ImmutableSet> getRawTypes(Type type) { + Preconditions.checkNotNull(type); + final ImmutableSet.Builder builder = ImmutableSet.builder(); + new TypeVisitor(){ + + @Override + void visitTypeVariable(TypeVariable t) { + this.visit(t.getBounds()); + } + + @Override + void visitWildcardType(WildcardType t) { + this.visit(t.getUpperBounds()); + } + + @Override + void visitParameterizedType(ParameterizedType t) { + builder.add((Class)t.getRawType()); + } + + @Override + void visitClass(Class t) { + builder.add(t); + } + + @Override + void visitGenericArrayType(GenericArrayType t) { + builder.add(Types.getArrayClass(TypeToken.getRawType(t.getGenericComponentType()))); + } + }.visit(type); + return builder.build(); + } + + @VisibleForTesting + static TypeToken toGenericType(Class cls) { + if (cls.isArray()) { + Type arrayOfGenericType = Types.newArrayType(TypeToken.toGenericType(cls.getComponentType()).runtimeType); + TypeToken result = TypeToken.of(arrayOfGenericType); + return result; + } + Type[] typeParams = cls.getTypeParameters(); + if (typeParams.length > 0) { + TypeToken type = TypeToken.of(Types.newParameterizedType(cls, typeParams)); + return type; + } + return TypeToken.of(cls); + } + + private TypeToken getSupertypeFromUpperBounds(Class supertype, Type[] upperBounds) { + for (Type upperBound : upperBounds) { + TypeToken bound = TypeToken.of(upperBound); + if (!TypeToken.of(supertype).isAssignableFrom(bound)) continue; + TypeToken result = bound.getSupertype(supertype); + return result; + } + String string = String.valueOf(String.valueOf(supertype)); + String string2 = String.valueOf(String.valueOf(this)); + throw new IllegalArgumentException(new StringBuilder(23 + string.length() + string2.length()).append(string).append(" isn't a super type of ").append(string2).toString()); + } + + private TypeToken getSubtypeFromLowerBounds(Class subclass, Type[] lowerBounds) { + int i$ = 0; + Type[] arr$ = lowerBounds; + int len$ = arr$.length; + if (i$ < len$) { + Type lowerBound = arr$[i$]; + TypeToken bound = TypeToken.of(lowerBound); + return bound.getSubtype(subclass); + } + String string = String.valueOf(String.valueOf(subclass)); + String string2 = String.valueOf(String.valueOf(this)); + throw new IllegalArgumentException(new StringBuilder(21 + string.length() + string2.length()).append(string).append(" isn't a subclass of ").append(string2).toString()); + } + + private TypeToken getArraySupertype(Class supertype) { + TypeToken componentType = Preconditions.checkNotNull(this.getComponentType(), "%s isn't a super type of %s", supertype, this); + TypeToken componentSupertype = componentType.getSupertype(supertype.getComponentType()); + TypeToken result = TypeToken.of(TypeToken.newArrayClassOrGenericArrayType(componentSupertype.runtimeType)); + return result; + } + + private TypeToken getArraySubtype(Class subclass) { + TypeToken componentSubtype = this.getComponentType().getSubtype(subclass.getComponentType()); + TypeToken result = TypeToken.of(TypeToken.newArrayClassOrGenericArrayType(componentSubtype.runtimeType)); + return result; + } + + private Type resolveTypeArgsForSubclass(Class subclass) { + if (this.runtimeType instanceof Class) { + return subclass; + } + TypeToken genericSubtype = TypeToken.toGenericType(subclass); + Type supertypeWithArgsFromSubtype = genericSubtype.getSupertype(this.getRawType()).runtimeType; + return new TypeResolver().where(supertypeWithArgsFromSubtype, this.runtimeType).resolveType(genericSubtype.runtimeType); + } + + private static Type newArrayClassOrGenericArrayType(Type componentType) { + return Types.JavaVersion.JAVA7.newArrayType(componentType); + } + + private static abstract class TypeCollector { + static final TypeCollector> FOR_GENERIC_TYPE = new TypeCollector>(){ + + @Override + Class getRawType(TypeToken type) { + return type.getRawType(); + } + + @Override + Iterable> getInterfaces(TypeToken type) { + return type.getGenericInterfaces(); + } + + @Override + @Nullable + TypeToken getSuperclass(TypeToken type) { + return type.getGenericSuperclass(); + } + }; + static final TypeCollector> FOR_RAW_TYPE = new TypeCollector>(){ + + @Override + Class getRawType(Class type) { + return type; + } + + @Override + Iterable> getInterfaces(Class type) { + return Arrays.asList(type.getInterfaces()); + } + + @Override + @Nullable + Class getSuperclass(Class type) { + return type.getSuperclass(); + } + }; + + private TypeCollector() { + } + + final TypeCollector classesOnly() { + return new ForwardingTypeCollector(this){ + + @Override + Iterable getInterfaces(K type) { + return ImmutableSet.of(); + } + + @Override + ImmutableList collectTypes(Iterable types) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Object type : types) { + if (this.getRawType(type).isInterface()) continue; + builder.add(type); + } + return super.collectTypes(builder.build()); + } + }; + } + + final ImmutableList collectTypes(K type) { + return this.collectTypes((Iterable)ImmutableList.of(type)); + } + + ImmutableList collectTypes(Iterable types) { + HashMap map = Maps.newHashMap(); + for (K type : types) { + this.collectTypes(type, map); + } + return TypeCollector.sortKeysByValue(map, Ordering.natural().reverse()); + } + + private int collectTypes(K type, Map map) { + Integer existing = map.get(this); + if (existing != null) { + return existing; + } + int aboveMe = this.getRawType(type).isInterface() ? 1 : 0; + for (K interfaceType : this.getInterfaces(type)) { + aboveMe = Math.max(aboveMe, this.collectTypes(interfaceType, map)); + } + K superclass = this.getSuperclass(type); + if (superclass != null) { + aboveMe = Math.max(aboveMe, this.collectTypes(superclass, map)); + } + map.put(type, aboveMe + 1); + return aboveMe + 1; + } + + private static ImmutableList sortKeysByValue(final Map map, final Comparator valueComparator) { + Ordering keyOrdering = new Ordering(){ + + @Override + public int compare(K left, K right) { + return valueComparator.compare(map.get(left), map.get(right)); + } + }; + return keyOrdering.immutableSortedCopy(map.keySet()); + } + + abstract Class getRawType(K var1); + + abstract Iterable getInterfaces(K var1); + + @Nullable + abstract K getSuperclass(K var1); + + private static class ForwardingTypeCollector + extends TypeCollector { + private final TypeCollector delegate; + + ForwardingTypeCollector(TypeCollector delegate) { + this.delegate = delegate; + } + + @Override + Class getRawType(K type) { + return this.delegate.getRawType(type); + } + + @Override + Iterable getInterfaces(K type) { + return this.delegate.getInterfaces(type); + } + + @Override + K getSuperclass(K type) { + return this.delegate.getSuperclass(type); + } + } + } + + private static final class SimpleTypeToken + extends TypeToken { + private static final long serialVersionUID = 0L; + + SimpleTypeToken(Type type) { + super(type); + } + } + + private static enum TypeFilter implements Predicate> + { + IGNORE_TYPE_VARIABLE_OR_WILDCARD{ + + @Override + public boolean apply(TypeToken type) { + return !(((TypeToken)type).runtimeType instanceof TypeVariable) && !(((TypeToken)type).runtimeType instanceof WildcardType); + } + } + , + INTERFACE_ONLY{ + + @Override + public boolean apply(TypeToken type) { + return type.getRawType().isInterface(); + } + }; + + } + + private final class ClassSet + extends TypeSet { + private transient ImmutableSet> classes; + private static final long serialVersionUID = 0L; + + private ClassSet() { + } + + @Override + protected Set> delegate() { + ImmutableSet result = this.classes; + if (result == null) { + ImmutableList collectedTypes = TypeCollector.FOR_GENERIC_TYPE.classesOnly().collectTypes(TypeToken.this); + this.classes = FluentIterable.from(collectedTypes).filter(TypeFilter.IGNORE_TYPE_VARIABLE_OR_WILDCARD).toSet(); + return this.classes; + } + return result; + } + + @Override + public TypeSet classes() { + return this; + } + + @Override + public Set> rawTypes() { + ImmutableList> collectedTypes = TypeCollector.FOR_RAW_TYPE.classesOnly().collectTypes(TypeToken.this.getImmediateRawTypes()); + return ImmutableSet.copyOf(collectedTypes); + } + + @Override + public TypeSet interfaces() { + throw new UnsupportedOperationException("classes().interfaces() not supported."); + } + + private Object readResolve() { + return TypeToken.this.getTypes().classes(); + } + } + + private final class InterfaceSet + extends TypeSet { + private final transient TypeSet allTypes; + private transient ImmutableSet> interfaces; + private static final long serialVersionUID = 0L; + + InterfaceSet(TypeSet allTypes) { + this.allTypes = allTypes; + } + + @Override + protected Set> delegate() { + ImmutableSet result = this.interfaces; + if (result == null) { + this.interfaces = FluentIterable.from(this.allTypes).filter(TypeFilter.INTERFACE_ONLY).toSet(); + return this.interfaces; + } + return result; + } + + @Override + public TypeSet interfaces() { + return this; + } + + @Override + public Set> rawTypes() { + ImmutableList> collectedTypes = TypeCollector.FOR_RAW_TYPE.collectTypes(TypeToken.this.getImmediateRawTypes()); + return FluentIterable.from(collectedTypes).filter(new Predicate>(){ + + @Override + public boolean apply(Class type) { + return type.isInterface(); + } + }).toSet(); + } + + @Override + public TypeSet classes() { + throw new UnsupportedOperationException("interfaces().classes() not supported."); + } + + private Object readResolve() { + return TypeToken.this.getTypes().interfaces(); + } + } + + public class TypeSet + extends ForwardingSet> + implements Serializable { + private transient ImmutableSet> types; + private static final long serialVersionUID = 0L; + + TypeSet() { + } + + public TypeSet interfaces() { + return new InterfaceSet(this); + } + + public TypeSet classes() { + return new ClassSet(); + } + + @Override + protected Set> delegate() { + ImmutableSet filteredTypes = this.types; + if (filteredTypes == null) { + ImmutableList collectedTypes = TypeCollector.FOR_GENERIC_TYPE.collectTypes(TypeToken.this); + this.types = FluentIterable.from(collectedTypes).filter(TypeFilter.IGNORE_TYPE_VARIABLE_OR_WILDCARD).toSet(); + return this.types; + } + return filteredTypes; + } + + public Set> rawTypes() { + ImmutableList> collectedTypes = TypeCollector.FOR_RAW_TYPE.collectTypes(TypeToken.this.getImmediateRawTypes()); + return ImmutableSet.copyOf(collectedTypes); + } + } +} diff --git a/src/com/google/common/reflect/TypeVisitor.java b/src/com/google/common/reflect/TypeVisitor.java new file mode 100644 index 0000000..8b62951 --- /dev/null +++ b/src/com/google/common/reflect/TypeVisitor.java @@ -0,0 +1,68 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.collect.Sets; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Set; +import javax.annotation.concurrent.NotThreadSafe; + +@NotThreadSafe +abstract class TypeVisitor { + private final Set visited = Sets.newHashSet(); + + TypeVisitor() { + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public final void visit(Type ... types) { + for (Type type : types) { + if (type == null || !this.visited.add(type)) continue; + boolean succeeded = false; + try { + if (type instanceof TypeVariable) { + this.visitTypeVariable((TypeVariable)type); + } else if (type instanceof WildcardType) { + this.visitWildcardType((WildcardType)type); + } else if (type instanceof ParameterizedType) { + this.visitParameterizedType((ParameterizedType)type); + } else if (type instanceof Class) { + this.visitClass((Class)type); + } else if (type instanceof GenericArrayType) { + this.visitGenericArrayType((GenericArrayType)type); + } else { + String string = String.valueOf(String.valueOf(type)); + throw new AssertionError((Object)new StringBuilder(14 + string.length()).append("Unknown type: ").append(string).toString()); + } + succeeded = true; + } + finally { + if (!succeeded) { + this.visited.remove(type); + } + } + } + } + + void visitClass(Class t) { + } + + void visitGenericArrayType(GenericArrayType t) { + } + + void visitParameterizedType(ParameterizedType t) { + } + + void visitTypeVariable(TypeVariable t) { + } + + void visitWildcardType(WildcardType t) { + } +} diff --git a/src/com/google/common/reflect/Types.java b/src/com/google/common/reflect/Types.java new file mode 100644 index 0000000..f41c322 --- /dev/null +++ b/src/com/google/common/reflect/Types.java @@ -0,0 +1,491 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.reflect; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.reflect.TypeCapture; +import com.google.common.reflect.TypeVisitor; +import java.io.Serializable; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.Nullable; + +final class Types { + private static final Function TYPE_NAME = new Function(){ + + @Override + public String apply(Type from) { + return JavaVersion.CURRENT.typeName(from); + } + }; + private static final Joiner COMMA_JOINER = Joiner.on(", ").useForNull("null"); + + static Type newArrayType(Type componentType) { + if (componentType instanceof WildcardType) { + WildcardType wildcard = (WildcardType)componentType; + Type[] lowerBounds = wildcard.getLowerBounds(); + Preconditions.checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds."); + if (lowerBounds.length == 1) { + return Types.supertypeOf(Types.newArrayType(lowerBounds[0])); + } + Type[] upperBounds = wildcard.getUpperBounds(); + Preconditions.checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound."); + return Types.subtypeOf(Types.newArrayType(upperBounds[0])); + } + return JavaVersion.CURRENT.newArrayType(componentType); + } + + static ParameterizedType newParameterizedTypeWithOwner(@Nullable Type ownerType, Class rawType, Type ... arguments) { + if (ownerType == null) { + return Types.newParameterizedType(rawType, arguments); + } + Preconditions.checkNotNull(arguments); + Preconditions.checkArgument(rawType.getEnclosingClass() != null, "Owner type for unenclosed %s", rawType); + return new ParameterizedTypeImpl(ownerType, rawType, arguments); + } + + static ParameterizedType newParameterizedType(Class rawType, Type ... arguments) { + return new ParameterizedTypeImpl(ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType), rawType, arguments); + } + + static TypeVariable newArtificialTypeVariable(D declaration, String name, Type ... bounds) { + Type[] typeArray; + if (bounds.length == 0) { + Type[] typeArray2 = new Type[1]; + typeArray = typeArray2; + typeArray2[0] = Object.class; + } else { + typeArray = bounds; + } + return new TypeVariableImpl(declaration, name, typeArray); + } + + @VisibleForTesting + static WildcardType subtypeOf(Type upperBound) { + return new WildcardTypeImpl(new Type[0], new Type[]{upperBound}); + } + + @VisibleForTesting + static WildcardType supertypeOf(Type lowerBound) { + return new WildcardTypeImpl(new Type[]{lowerBound}, new Type[]{Object.class}); + } + + static String toString(Type type) { + return type instanceof Class ? ((Class)type).getName() : type.toString(); + } + + @Nullable + static Type getComponentType(Type type) { + Preconditions.checkNotNull(type); + final AtomicReference result = new AtomicReference(); + new TypeVisitor(){ + + @Override + void visitTypeVariable(TypeVariable t) { + result.set(Types.subtypeOfComponentType(t.getBounds())); + } + + @Override + void visitWildcardType(WildcardType t) { + result.set(Types.subtypeOfComponentType(t.getUpperBounds())); + } + + @Override + void visitGenericArrayType(GenericArrayType t) { + result.set(t.getGenericComponentType()); + } + + @Override + void visitClass(Class t) { + result.set(t.getComponentType()); + } + }.visit(type); + return (Type)result.get(); + } + + @Nullable + private static Type subtypeOfComponentType(Type[] bounds) { + for (Type bound : bounds) { + Class componentClass; + Type componentType = Types.getComponentType(bound); + if (componentType == null) continue; + if (componentType instanceof Class && (componentClass = (Class)componentType).isPrimitive()) { + return componentClass; + } + return Types.subtypeOf(componentType); + } + return null; + } + + private static Type[] toArray(Collection types) { + return types.toArray(new Type[types.size()]); + } + + private static Iterable filterUpperBounds(Iterable bounds) { + return Iterables.filter(bounds, Predicates.not(Predicates.equalTo(Object.class))); + } + + private static void disallowPrimitiveType(Type[] types, String usedAs) { + for (Type type : types) { + if (!(type instanceof Class)) continue; + Class cls = (Class)type; + Preconditions.checkArgument(!cls.isPrimitive(), "Primitive type '%s' used as %s", cls, usedAs); + } + } + + static Class getArrayClass(Class componentType) { + return Array.newInstance(componentType, 0).getClass(); + } + + private Types() { + } + + static final class NativeTypeVariableEquals { + static final boolean NATIVE_TYPE_VARIABLE_ONLY = !NativeTypeVariableEquals.class.getTypeParameters()[0].equals(Types.newArtificialTypeVariable(NativeTypeVariableEquals.class, "X", new Type[0])); + + NativeTypeVariableEquals() { + } + } + + static enum JavaVersion { + JAVA6{ + + @Override + GenericArrayType newArrayType(Type componentType) { + return new GenericArrayTypeImpl(componentType); + } + + @Override + Type usedInGenericType(Type type) { + Class cls; + Preconditions.checkNotNull(type); + if (type instanceof Class && (cls = (Class)type).isArray()) { + return new GenericArrayTypeImpl(cls.getComponentType()); + } + return type; + } + } + , + JAVA7{ + + @Override + Type newArrayType(Type componentType) { + if (componentType instanceof Class) { + return Types.getArrayClass((Class)componentType); + } + return new GenericArrayTypeImpl(componentType); + } + + @Override + Type usedInGenericType(Type type) { + return Preconditions.checkNotNull(type); + } + } + , + JAVA8{ + + @Override + Type newArrayType(Type componentType) { + return JAVA7.newArrayType(componentType); + } + + @Override + Type usedInGenericType(Type type) { + return JAVA7.usedInGenericType(type); + } + + @Override + String typeName(Type type) { + try { + Method getTypeName = Type.class.getMethod("getTypeName", new Class[0]); + return (String)getTypeName.invoke(type, new Object[0]); + } + catch (NoSuchMethodException e) { + throw new AssertionError((Object)"Type.getTypeName should be available in Java 8"); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + }; + + static final JavaVersion CURRENT; + + abstract Type newArrayType(Type var1); + + abstract Type usedInGenericType(Type var1); + + String typeName(Type type) { + return Types.toString(type); + } + + final ImmutableList usedInGenericType(Type[] types) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Type type : types) { + builder.add(this.usedInGenericType(type)); + } + return builder.build(); + } + + static { + CURRENT = AnnotatedElement.class.isAssignableFrom(TypeVariable.class) ? JAVA8 : (new TypeCapture(){}.capture() instanceof Class ? JAVA7 : JAVA6); + } + } + + static final class WildcardTypeImpl + implements WildcardType, + Serializable { + private final ImmutableList lowerBounds; + private final ImmutableList upperBounds; + private static final long serialVersionUID = 0L; + + WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) { + Types.disallowPrimitiveType(lowerBounds, "lower bound for wildcard"); + Types.disallowPrimitiveType(upperBounds, "upper bound for wildcard"); + this.lowerBounds = JavaVersion.CURRENT.usedInGenericType(lowerBounds); + this.upperBounds = JavaVersion.CURRENT.usedInGenericType(upperBounds); + } + + @Override + public Type[] getLowerBounds() { + return Types.toArray(this.lowerBounds); + } + + @Override + public Type[] getUpperBounds() { + return Types.toArray(this.upperBounds); + } + + public boolean equals(Object obj) { + if (obj instanceof WildcardType) { + WildcardType that = (WildcardType)obj; + return this.lowerBounds.equals(Arrays.asList(that.getLowerBounds())) && this.upperBounds.equals(Arrays.asList(that.getUpperBounds())); + } + return false; + } + + public int hashCode() { + return this.lowerBounds.hashCode() ^ this.upperBounds.hashCode(); + } + + public String toString() { + StringBuilder builder = new StringBuilder("?"); + for (Type lowerBound : this.lowerBounds) { + builder.append(" super ").append(JavaVersion.CURRENT.typeName(lowerBound)); + } + for (Type upperBound : Types.filterUpperBounds(this.upperBounds)) { + builder.append(" extends ").append(JavaVersion.CURRENT.typeName(upperBound)); + } + return builder.toString(); + } + } + + private static final class TypeVariableImpl + implements TypeVariable { + private final D genericDeclaration; + private final String name; + private final ImmutableList bounds; + + TypeVariableImpl(D genericDeclaration, String name, Type[] bounds) { + Types.disallowPrimitiveType(bounds, "bound for type variable"); + this.genericDeclaration = (GenericDeclaration)Preconditions.checkNotNull(genericDeclaration); + this.name = Preconditions.checkNotNull(name); + this.bounds = ImmutableList.copyOf(bounds); + } + + @Override + public Type[] getBounds() { + return Types.toArray(this.bounds); + } + + @Override + public D getGenericDeclaration() { + return this.genericDeclaration; + } + + @Override + public String getName() { + return this.name; + } + + public String toString() { + return this.name; + } + + public int hashCode() { + return this.genericDeclaration.hashCode() ^ this.name.hashCode(); + } + + public boolean equals(Object obj) { + if (NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) { + if (obj instanceof TypeVariableImpl) { + TypeVariableImpl that = (TypeVariableImpl)obj; + return this.name.equals(that.getName()) && this.genericDeclaration.equals(that.getGenericDeclaration()) && this.bounds.equals(that.bounds); + } + return false; + } + if (obj instanceof TypeVariable) { + TypeVariable that = (TypeVariable)obj; + return this.name.equals(that.getName()) && this.genericDeclaration.equals(that.getGenericDeclaration()); + } + return false; + } + } + + private static final class ParameterizedTypeImpl + implements ParameterizedType, + Serializable { + private final Type ownerType; + private final ImmutableList argumentsList; + private final Class rawType; + private static final long serialVersionUID = 0L; + + ParameterizedTypeImpl(@Nullable Type ownerType, Class rawType, Type[] typeArguments) { + Preconditions.checkNotNull(rawType); + Preconditions.checkArgument(typeArguments.length == rawType.getTypeParameters().length); + Types.disallowPrimitiveType(typeArguments, "type parameter"); + this.ownerType = ownerType; + this.rawType = rawType; + this.argumentsList = JavaVersion.CURRENT.usedInGenericType(typeArguments); + } + + @Override + public Type[] getActualTypeArguments() { + return Types.toArray(this.argumentsList); + } + + @Override + public Type getRawType() { + return this.rawType; + } + + @Override + public Type getOwnerType() { + return this.ownerType; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + if (this.ownerType != null) { + builder.append(JavaVersion.CURRENT.typeName(this.ownerType)).append('.'); + } + builder.append(this.rawType.getName()).append('<').append(COMMA_JOINER.join(Iterables.transform(this.argumentsList, TYPE_NAME))).append('>'); + return builder.toString(); + } + + public int hashCode() { + return (this.ownerType == null ? 0 : this.ownerType.hashCode()) ^ this.argumentsList.hashCode() ^ this.rawType.hashCode(); + } + + public boolean equals(Object other) { + if (!(other instanceof ParameterizedType)) { + return false; + } + ParameterizedType that = (ParameterizedType)other; + return this.getRawType().equals(that.getRawType()) && Objects.equal(this.getOwnerType(), that.getOwnerType()) && Arrays.equals(this.getActualTypeArguments(), that.getActualTypeArguments()); + } + } + + private static final class GenericArrayTypeImpl + implements GenericArrayType, + Serializable { + private final Type componentType; + private static final long serialVersionUID = 0L; + + GenericArrayTypeImpl(Type componentType) { + this.componentType = JavaVersion.CURRENT.usedInGenericType(componentType); + } + + @Override + public Type getGenericComponentType() { + return this.componentType; + } + + public String toString() { + return String.valueOf(Types.toString(this.componentType)).concat("[]"); + } + + public int hashCode() { + return this.componentType.hashCode(); + } + + public boolean equals(Object obj) { + if (obj instanceof GenericArrayType) { + GenericArrayType that = (GenericArrayType)obj; + return Objects.equal(this.getGenericComponentType(), that.getGenericComponentType()); + } + return false; + } + } + + private static enum ClassOwnership { + OWNED_BY_ENCLOSING_CLASS{ + + @Override + @Nullable + Class getOwnerType(Class rawType) { + return rawType.getEnclosingClass(); + } + } + , + LOCAL_CLASS_HAS_NO_OWNER{ + + @Override + @Nullable + Class getOwnerType(Class rawType) { + if (rawType.isLocalClass()) { + return null; + } + return rawType.getEnclosingClass(); + } + }; + + static final ClassOwnership JVM_BEHAVIOR; + + @Nullable + abstract Class getOwnerType(Class var1); + + private static ClassOwnership detectJvmBehavior() { + class LocalClass { + LocalClass() { + } + } + Class subclass = new LocalClass(){ + { + } + }.getClass(); + ParameterizedType parameterizedType = (ParameterizedType)subclass.getGenericSuperclass(); + for (ClassOwnership behavior : ClassOwnership.values()) { + if (behavior.getOwnerType(LocalClass.class) != parameterizedType.getOwnerType()) continue; + return behavior; + } + throw new AssertionError(); + } + + static { + JVM_BEHAVIOR = ClassOwnership.detectJvmBehavior(); + } + } +} diff --git a/src/com/google/common/reflect/package-info.java b/src/com/google/common/reflect/package-info.java new file mode 100644 index 0000000..643295b --- /dev/null +++ b/src/com/google/common/reflect/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.reflect; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/util/concurrent/AbstractCheckedFuture.java b/src/com/google/common/util/concurrent/AbstractCheckedFuture.java new file mode 100644 index 0000000..73cf2a8 --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractCheckedFuture.java @@ -0,0 +1,58 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ForwardingListenableFuture; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public abstract class AbstractCheckedFuture +extends ForwardingListenableFuture.SimpleForwardingListenableFuture +implements CheckedFuture { + protected AbstractCheckedFuture(ListenableFuture delegate) { + super(delegate); + } + + protected abstract X mapException(Exception var1); + + @Override + public V checkedGet() throws X { + try { + return this.get(); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw this.mapException(e); + } + catch (CancellationException e) { + throw this.mapException(e); + } + catch (ExecutionException e) { + throw this.mapException(e); + } + } + + @Override + public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X { + try { + return this.get(timeout, unit); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw this.mapException(e); + } + catch (CancellationException e) { + throw this.mapException(e); + } + catch (ExecutionException e) { + throw this.mapException(e); + } + } +} diff --git a/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java new file mode 100644 index 0000000..dadfefd --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java @@ -0,0 +1,156 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.util.concurrent.AbstractService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Beta +public abstract class AbstractExecutionThreadService +implements Service { + private static final Logger logger = Logger.getLogger(AbstractExecutionThreadService.class.getName()); + private final Service delegate = new AbstractService(){ + + @Override + protected final void doStart() { + Executor executor = MoreExecutors.renamingDecorator(AbstractExecutionThreadService.this.executor(), new Supplier(){ + + @Override + public String get() { + return AbstractExecutionThreadService.this.serviceName(); + } + }); + executor.execute(new Runnable(){ + + @Override + public void run() { + try { + AbstractExecutionThreadService.this.startUp(); + this.notifyStarted(); + if (this.isRunning()) { + try { + AbstractExecutionThreadService.this.run(); + } + catch (Throwable t) { + try { + AbstractExecutionThreadService.this.shutDown(); + } + catch (Exception ignored) { + logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored); + } + throw t; + } + } + AbstractExecutionThreadService.this.shutDown(); + this.notifyStopped(); + } + catch (Throwable t) { + this.notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + + @Override + protected void doStop() { + AbstractExecutionThreadService.this.triggerShutdown(); + } + }; + + protected AbstractExecutionThreadService() { + } + + protected void startUp() throws Exception { + } + + protected abstract void run() throws Exception; + + protected void shutDown() throws Exception { + } + + protected void triggerShutdown() { + } + + protected Executor executor() { + return new Executor(){ + + @Override + public void execute(Runnable command) { + MoreExecutors.newThread(AbstractExecutionThreadService.this.serviceName(), command).start(); + } + }; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.serviceName())); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString(); + } + + @Override + public final boolean isRunning() { + return this.delegate.isRunning(); + } + + @Override + public final Service.State state() { + return this.delegate.state(); + } + + @Override + public final void addListener(Service.Listener listener, Executor executor) { + this.delegate.addListener(listener, executor); + } + + @Override + public final Throwable failureCause() { + return this.delegate.failureCause(); + } + + @Override + public final Service startAsync() { + this.delegate.startAsync(); + return this; + } + + @Override + public final Service stopAsync() { + this.delegate.stopAsync(); + return this; + } + + @Override + public final void awaitRunning() { + this.delegate.awaitRunning(); + } + + @Override + public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitRunning(timeout, unit); + } + + @Override + public final void awaitTerminated() { + this.delegate.awaitTerminated(); + } + + @Override + public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitTerminated(timeout, unit); + } + + protected String serviceName() { + return this.getClass().getSimpleName(); + } +} diff --git a/src/com/google/common/util/concurrent/AbstractFuture.java b/src/com/google/common/util/concurrent/AbstractFuture.java new file mode 100644 index 0000000..ff95417 --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractFuture.java @@ -0,0 +1,185 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ExecutionList; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import javax.annotation.Nullable; + +public abstract class AbstractFuture +implements ListenableFuture { + private final Sync sync = new Sync(); + private final ExecutionList executionList = new ExecutionList(); + + protected AbstractFuture() { + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, ExecutionException { + return this.sync.get(unit.toNanos(timeout)); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + return this.sync.get(); + } + + @Override + public boolean isDone() { + return this.sync.isDone(); + } + + @Override + public boolean isCancelled() { + return this.sync.isCancelled(); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (!this.sync.cancel(mayInterruptIfRunning)) { + return false; + } + this.executionList.execute(); + if (mayInterruptIfRunning) { + this.interruptTask(); + } + return true; + } + + protected void interruptTask() { + } + + protected final boolean wasInterrupted() { + return this.sync.wasInterrupted(); + } + + @Override + public void addListener(Runnable listener, Executor exec) { + this.executionList.add(listener, exec); + } + + protected boolean set(@Nullable V value) { + boolean result = this.sync.set(value); + if (result) { + this.executionList.execute(); + } + return result; + } + + protected boolean setException(Throwable throwable) { + boolean result = this.sync.setException(Preconditions.checkNotNull(throwable)); + if (result) { + this.executionList.execute(); + } + return result; + } + + static final CancellationException cancellationExceptionWithCause(@Nullable String message, @Nullable Throwable cause) { + CancellationException exception = new CancellationException(message); + exception.initCause(cause); + return exception; + } + + static final class Sync + extends AbstractQueuedSynchronizer { + private static final long serialVersionUID = 0L; + static final int RUNNING = 0; + static final int COMPLETING = 1; + static final int COMPLETED = 2; + static final int CANCELLED = 4; + static final int INTERRUPTED = 8; + private V value; + private Throwable exception; + + Sync() { + } + + @Override + protected int tryAcquireShared(int ignored) { + if (this.isDone()) { + return 1; + } + return -1; + } + + @Override + protected boolean tryReleaseShared(int finalState) { + this.setState(finalState); + return true; + } + + V get(long nanos) throws TimeoutException, CancellationException, ExecutionException, InterruptedException { + if (!this.tryAcquireSharedNanos(-1, nanos)) { + throw new TimeoutException("Timeout waiting for task."); + } + return this.getValue(); + } + + V get() throws CancellationException, ExecutionException, InterruptedException { + this.acquireSharedInterruptibly(-1); + return this.getValue(); + } + + private V getValue() throws CancellationException, ExecutionException { + int state = this.getState(); + switch (state) { + case 2: { + if (this.exception != null) { + throw new ExecutionException(this.exception); + } + return this.value; + } + case 4: + case 8: { + throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", this.exception); + } + } + int n = state; + throw new IllegalStateException(new StringBuilder(49).append("Error, synchronizer in invalid state: ").append(n).toString()); + } + + boolean isDone() { + return (this.getState() & 0xE) != 0; + } + + boolean isCancelled() { + return (this.getState() & 0xC) != 0; + } + + boolean wasInterrupted() { + return this.getState() == 8; + } + + boolean set(@Nullable V v) { + return this.complete(v, null, 2); + } + + boolean setException(Throwable t) { + return this.complete(null, t, 2); + } + + boolean cancel(boolean interrupt) { + return this.complete(null, null, interrupt ? 8 : 4); + } + + private boolean complete(@Nullable V v, @Nullable Throwable t, int finalState) { + boolean doCompletion = this.compareAndSetState(0, 1); + if (doCompletion) { + this.value = v; + this.exception = (finalState & 0xC) != 0 ? new CancellationException("Future.cancel() was called.") : t; + this.releaseShared(finalState); + } else if (this.getState() == 1) { + this.acquireShared(-1); + } + return doCompletion; + } + } +} diff --git a/src/com/google/common/util/concurrent/AbstractIdleService.java b/src/com/google/common/util/concurrent/AbstractIdleService.java new file mode 100644 index 0000000..c1d4d3d --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractIdleService.java @@ -0,0 +1,145 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.util.concurrent.AbstractService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public abstract class AbstractIdleService +implements Service { + private final Supplier threadNameSupplier = new Supplier(){ + + @Override + public String get() { + String string = String.valueOf(String.valueOf(AbstractIdleService.this.serviceName())); + String string2 = String.valueOf(String.valueOf((Object)AbstractIdleService.this.state())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append(" ").append(string2).toString(); + } + }; + private final Service delegate = new AbstractService(){ + + @Override + protected final void doStart() { + MoreExecutors.renamingDecorator(AbstractIdleService.this.executor(), (Supplier)AbstractIdleService.this.threadNameSupplier).execute(new Runnable(){ + + @Override + public void run() { + try { + AbstractIdleService.this.startUp(); + this.notifyStarted(); + } + catch (Throwable t) { + this.notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + + @Override + protected final void doStop() { + MoreExecutors.renamingDecorator(AbstractIdleService.this.executor(), (Supplier)AbstractIdleService.this.threadNameSupplier).execute(new Runnable(){ + + @Override + public void run() { + try { + AbstractIdleService.this.shutDown(); + this.notifyStopped(); + } + catch (Throwable t) { + this.notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + }; + + protected AbstractIdleService() { + } + + protected abstract void startUp() throws Exception; + + protected abstract void shutDown() throws Exception; + + protected Executor executor() { + return new Executor(){ + + @Override + public void execute(Runnable command) { + MoreExecutors.newThread((String)AbstractIdleService.this.threadNameSupplier.get(), command).start(); + } + }; + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.serviceName())); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString(); + } + + @Override + public final boolean isRunning() { + return this.delegate.isRunning(); + } + + @Override + public final Service.State state() { + return this.delegate.state(); + } + + @Override + public final void addListener(Service.Listener listener, Executor executor) { + this.delegate.addListener(listener, executor); + } + + @Override + public final Throwable failureCause() { + return this.delegate.failureCause(); + } + + @Override + public final Service startAsync() { + this.delegate.startAsync(); + return this; + } + + @Override + public final Service stopAsync() { + this.delegate.stopAsync(); + return this; + } + + @Override + public final void awaitRunning() { + this.delegate.awaitRunning(); + } + + @Override + public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitRunning(timeout, unit); + } + + @Override + public final void awaitTerminated() { + this.delegate.awaitTerminated(); + } + + @Override + public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitTerminated(timeout, unit); + } + + protected String serviceName() { + return this.getClass().getSimpleName(); + } +} diff --git a/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java b/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java new file mode 100644 index 0000000..ddce9d6 --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java @@ -0,0 +1,40 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ListeningExecutorService; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.Callable; +import javax.annotation.Nullable; + +@Beta +public abstract class AbstractListeningExecutorService +extends AbstractExecutorService +implements ListeningExecutorService { + protected final ListenableFutureTask newTaskFor(Runnable runnable, T value) { + return ListenableFutureTask.create(runnable, value); + } + + protected final ListenableFutureTask newTaskFor(Callable callable) { + return ListenableFutureTask.create(callable); + } + + @Override + public ListenableFuture submit(Runnable task) { + return (ListenableFuture)super.submit(task); + } + + @Override + public ListenableFuture submit(Runnable task, @Nullable T result) { + return (ListenableFuture)super.submit(task, result); + } + + @Override + public ListenableFuture submit(Callable task) { + return (ListenableFuture)super.submit(task); + } +} diff --git a/src/com/google/common/util/concurrent/AbstractScheduledService.java b/src/com/google/common/util/concurrent/AbstractScheduledService.java new file mode 100644 index 0000000..8f4933a --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractScheduledService.java @@ -0,0 +1,334 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.util.concurrent.AbstractService; +import com.google.common.util.concurrent.ForwardingFuture; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + +@Beta +public abstract class AbstractScheduledService +implements Service { + private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName()); + private final AbstractService delegate = new AbstractService(){ + private volatile Future runningTask; + private volatile ScheduledExecutorService executorService; + private final ReentrantLock lock = new ReentrantLock(); + private final Runnable task = new Runnable(){ + + @Override + public void run() { + lock.lock(); + try { + AbstractScheduledService.this.runOneIteration(); + } + catch (Throwable t) { + try { + AbstractScheduledService.this.shutDown(); + } + catch (Exception ignored) { + logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored); + } + this.notifyFailed(t); + throw Throwables.propagate(t); + } + finally { + lock.unlock(); + } + } + }; + + @Override + protected final void doStart() { + this.executorService = MoreExecutors.renamingDecorator(AbstractScheduledService.this.executor(), new Supplier(){ + + @Override + public String get() { + String string = String.valueOf(String.valueOf(AbstractScheduledService.this.serviceName())); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append(" ").append(string2).toString(); + } + }); + this.executorService.execute(new Runnable(){ + + @Override + public void run() { + lock.lock(); + try { + AbstractScheduledService.this.startUp(); + runningTask = AbstractScheduledService.this.scheduler().schedule(AbstractScheduledService.this.delegate, executorService, task); + this.notifyStarted(); + } + catch (Throwable t) { + this.notifyFailed(t); + throw Throwables.propagate(t); + } + finally { + lock.unlock(); + } + } + }); + } + + @Override + protected final void doStop() { + this.runningTask.cancel(false); + this.executorService.execute(new Runnable(){ + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void run() { + try { + lock.lock(); + try { + if (this.state() != Service.State.STOPPING) { + return; + } + AbstractScheduledService.this.shutDown(); + } + finally { + lock.unlock(); + } + this.notifyStopped(); + } + catch (Throwable t) { + this.notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + }; + + protected AbstractScheduledService() { + } + + protected abstract void runOneIteration() throws Exception; + + protected void startUp() throws Exception { + } + + protected void shutDown() throws Exception { + } + + protected abstract Scheduler scheduler(); + + protected ScheduledExecutorService executor() { + final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory(){ + + @Override + public Thread newThread(Runnable runnable) { + return MoreExecutors.newThread(AbstractScheduledService.this.serviceName(), runnable); + } + }); + this.addListener(new Service.Listener(){ + + @Override + public void terminated(Service.State from) { + executor.shutdown(); + } + + @Override + public void failed(Service.State from, Throwable failure) { + executor.shutdown(); + } + }, MoreExecutors.directExecutor()); + return executor; + } + + protected String serviceName() { + return this.getClass().getSimpleName(); + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.serviceName())); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString(); + } + + @Override + public final boolean isRunning() { + return this.delegate.isRunning(); + } + + @Override + public final Service.State state() { + return this.delegate.state(); + } + + @Override + public final void addListener(Service.Listener listener, Executor executor) { + this.delegate.addListener(listener, executor); + } + + @Override + public final Throwable failureCause() { + return this.delegate.failureCause(); + } + + @Override + public final Service startAsync() { + this.delegate.startAsync(); + return this; + } + + @Override + public final Service stopAsync() { + this.delegate.stopAsync(); + return this; + } + + @Override + public final void awaitRunning() { + this.delegate.awaitRunning(); + } + + @Override + public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitRunning(timeout, unit); + } + + @Override + public final void awaitTerminated() { + this.delegate.awaitTerminated(); + } + + @Override + public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { + this.delegate.awaitTerminated(timeout, unit); + } + + @Beta + public static abstract class CustomScheduler + extends Scheduler { + @Override + final Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable runnable) { + ReschedulableCallable task = new ReschedulableCallable(service, executor, runnable); + task.reschedule(); + return task; + } + + protected abstract Schedule getNextSchedule() throws Exception; + + @Beta + protected static final class Schedule { + private final long delay; + private final TimeUnit unit; + + public Schedule(long delay, TimeUnit unit) { + this.delay = delay; + this.unit = Preconditions.checkNotNull(unit); + } + } + + private class ReschedulableCallable + extends ForwardingFuture + implements Callable { + private final Runnable wrappedRunnable; + private final ScheduledExecutorService executor; + private final AbstractService service; + private final ReentrantLock lock = new ReentrantLock(); + @GuardedBy(value="lock") + private Future currentFuture; + + ReschedulableCallable(AbstractService service, ScheduledExecutorService executor, Runnable runnable) { + this.wrappedRunnable = runnable; + this.executor = executor; + this.service = service; + } + + @Override + public Void call() throws Exception { + this.wrappedRunnable.run(); + this.reschedule(); + return null; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void reschedule() { + this.lock.lock(); + try { + if (this.currentFuture == null || !this.currentFuture.isCancelled()) { + Schedule schedule = CustomScheduler.this.getNextSchedule(); + this.currentFuture = this.executor.schedule(this, schedule.delay, schedule.unit); + } + } + catch (Throwable e) { + this.service.notifyFailed(e); + } + finally { + this.lock.unlock(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + this.lock.lock(); + try { + boolean bl = this.currentFuture.cancel(mayInterruptIfRunning); + return bl; + } + finally { + this.lock.unlock(); + } + } + + @Override + protected Future delegate() { + throw new UnsupportedOperationException("Only cancel is supported by this future"); + } + } + } + + public static abstract class Scheduler { + public static Scheduler newFixedDelaySchedule(final long initialDelay, final long delay, final TimeUnit unit) { + return new Scheduler(){ + + @Override + public Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable task) { + return executor.scheduleWithFixedDelay(task, initialDelay, delay, unit); + } + }; + } + + public static Scheduler newFixedRateSchedule(final long initialDelay, final long period, final TimeUnit unit) { + return new Scheduler(){ + + @Override + public Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable task) { + return executor.scheduleAtFixedRate(task, initialDelay, period, unit); + } + }; + } + + abstract Future schedule(AbstractService var1, ScheduledExecutorService var2, Runnable var3); + + private Scheduler() { + } + } +} diff --git a/src/com/google/common/util/concurrent/AbstractService.java b/src/com/google/common/util/concurrent/AbstractService.java new file mode 100644 index 0000000..85991ed --- /dev/null +++ b/src/com/google/common/util/concurrent/AbstractService.java @@ -0,0 +1,479 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ListenerCallQueue; +import com.google.common.util.concurrent.Monitor; +import com.google.common.util.concurrent.Service; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; + +@Beta +public abstract class AbstractService +implements Service { + private static final ListenerCallQueue.Callback STARTING_CALLBACK = new ListenerCallQueue.Callback("starting()"){ + + @Override + void call(Service.Listener listener) { + listener.starting(); + } + }; + private static final ListenerCallQueue.Callback RUNNING_CALLBACK = new ListenerCallQueue.Callback("running()"){ + + @Override + void call(Service.Listener listener) { + listener.running(); + } + }; + private static final ListenerCallQueue.Callback STOPPING_FROM_STARTING_CALLBACK = AbstractService.stoppingCallback(Service.State.STARTING); + private static final ListenerCallQueue.Callback STOPPING_FROM_RUNNING_CALLBACK = AbstractService.stoppingCallback(Service.State.RUNNING); + private static final ListenerCallQueue.Callback TERMINATED_FROM_NEW_CALLBACK = AbstractService.terminatedCallback(Service.State.NEW); + private static final ListenerCallQueue.Callback TERMINATED_FROM_RUNNING_CALLBACK = AbstractService.terminatedCallback(Service.State.RUNNING); + private static final ListenerCallQueue.Callback TERMINATED_FROM_STOPPING_CALLBACK = AbstractService.terminatedCallback(Service.State.STOPPING); + private final Monitor monitor = new Monitor(); + private final Monitor.Guard isStartable = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return AbstractService.this.state() == Service.State.NEW; + } + }; + private final Monitor.Guard isStoppable = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return AbstractService.this.state().compareTo(Service.State.RUNNING) <= 0; + } + }; + private final Monitor.Guard hasReachedRunning = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return AbstractService.this.state().compareTo(Service.State.RUNNING) >= 0; + } + }; + private final Monitor.Guard isStopped = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return AbstractService.this.state().isTerminal(); + } + }; + @GuardedBy(value="monitor") + private final List> listeners = Collections.synchronizedList(new ArrayList()); + @GuardedBy(value="monitor") + private volatile StateSnapshot snapshot = new StateSnapshot(Service.State.NEW); + + private static ListenerCallQueue.Callback terminatedCallback(final Service.State from) { + String string = String.valueOf(String.valueOf((Object)from)); + return new ListenerCallQueue.Callback(new StringBuilder(21 + string.length()).append("terminated({from = ").append(string).append("})").toString()){ + + @Override + void call(Service.Listener listener) { + listener.terminated(from); + } + }; + } + + private static ListenerCallQueue.Callback stoppingCallback(final Service.State from) { + String string = String.valueOf(String.valueOf((Object)from)); + return new ListenerCallQueue.Callback(new StringBuilder(19 + string.length()).append("stopping({from = ").append(string).append("})").toString()){ + + @Override + void call(Service.Listener listener) { + listener.stopping(from); + } + }; + } + + protected AbstractService() { + } + + protected abstract void doStart(); + + protected abstract void doStop(); + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final Service startAsync() { + if (this.monitor.enterIf(this.isStartable)) { + try { + this.snapshot = new StateSnapshot(Service.State.STARTING); + this.starting(); + this.doStart(); + } + catch (Throwable startupFailure) { + this.notifyFailed(startupFailure); + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } else { + String string = String.valueOf(String.valueOf(this)); + throw new IllegalStateException(new StringBuilder(33 + string.length()).append("Service ").append(string).append(" has already been started").toString()); + } + return this; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + * Enabled force condition propagation + * Lifted jumps to return sites + */ + @Override + public final Service stopAsync() { + if (!this.monitor.enterIf(this.isStoppable)) return this; + try { + Service.State previous = this.state(); + switch (previous) { + case NEW: { + this.snapshot = new StateSnapshot(Service.State.TERMINATED); + this.terminated(Service.State.NEW); + return this; + } + case STARTING: { + this.snapshot = new StateSnapshot(Service.State.STARTING, true, null); + this.stopping(Service.State.STARTING); + return this; + } + case RUNNING: { + this.snapshot = new StateSnapshot(Service.State.STOPPING); + this.stopping(Service.State.RUNNING); + this.doStop(); + return this; + } + case STOPPING: + case TERMINATED: + case FAILED: { + String string = String.valueOf(String.valueOf((Object)previous)); + throw new AssertionError((Object)new StringBuilder(45 + string.length()).append("isStoppable is incorrectly implemented, saw: ").append(string).toString()); + } + default: { + String string = String.valueOf(String.valueOf((Object)previous)); + throw new AssertionError((Object)new StringBuilder(18 + string.length()).append("Unexpected state: ").append(string).toString()); + } + } + } + catch (Throwable shutdownFailure) { + this.notifyFailed(shutdownFailure); + return this; + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final void awaitRunning() { + this.monitor.enterWhenUninterruptibly(this.hasReachedRunning); + try { + this.checkCurrentState(Service.State.RUNNING); + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { + if (this.monitor.enterWhenUninterruptibly(this.hasReachedRunning, timeout, unit)) { + try { + this.checkCurrentState(Service.State.RUNNING); + } + finally { + this.monitor.leave(); + } + } else { + String string = String.valueOf(String.valueOf(this)); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + throw new TimeoutException(new StringBuilder(66 + string.length() + string2.length()).append("Timed out waiting for ").append(string).append(" to reach the RUNNING state. ").append("Current state: ").append(string2).toString()); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final void awaitTerminated() { + this.monitor.enterWhenUninterruptibly(this.isStopped); + try { + this.checkCurrentState(Service.State.TERMINATED); + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { + if (this.monitor.enterWhenUninterruptibly(this.isStopped, timeout, unit)) { + try { + this.checkCurrentState(Service.State.TERMINATED); + } + finally { + this.monitor.leave(); + } + } else { + String string = String.valueOf(String.valueOf(this)); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + throw new TimeoutException(new StringBuilder(65 + string.length() + string2.length()).append("Timed out waiting for ").append(string).append(" to reach a terminal state. ").append("Current state: ").append(string2).toString()); + } + } + + @GuardedBy(value="monitor") + private void checkCurrentState(Service.State expected) { + Service.State actual = this.state(); + if (actual != expected) { + if (actual == Service.State.FAILED) { + String string = String.valueOf(String.valueOf((Object)expected)); + throw new IllegalStateException(new StringBuilder(55 + string.length()).append("Expected the service to be ").append(string).append(", but the service has FAILED").toString(), this.failureCause()); + } + String string = String.valueOf(String.valueOf((Object)expected)); + String string2 = String.valueOf(String.valueOf((Object)actual)); + throw new IllegalStateException(new StringBuilder(37 + string.length() + string2.length()).append("Expected the service to be ").append(string).append(", but was ").append(string2).toString()); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + protected final void notifyStarted() { + this.monitor.enter(); + try { + if (this.snapshot.state != Service.State.STARTING) { + String string = String.valueOf(String.valueOf((Object)this.snapshot.state)); + IllegalStateException failure = new IllegalStateException(new StringBuilder(43 + string.length()).append("Cannot notifyStarted() when the service is ").append(string).toString()); + this.notifyFailed(failure); + throw failure; + } + if (this.snapshot.shutdownWhenStartupFinishes) { + this.snapshot = new StateSnapshot(Service.State.STOPPING); + this.doStop(); + } else { + this.snapshot = new StateSnapshot(Service.State.RUNNING); + this.running(); + } + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + protected final void notifyStopped() { + this.monitor.enter(); + try { + Service.State previous = this.snapshot.state; + if (previous != Service.State.STOPPING && previous != Service.State.RUNNING) { + String string = String.valueOf(String.valueOf((Object)previous)); + IllegalStateException failure = new IllegalStateException(new StringBuilder(43 + string.length()).append("Cannot notifyStopped() when the service is ").append(string).toString()); + this.notifyFailed(failure); + throw failure; + } + this.snapshot = new StateSnapshot(Service.State.TERMINATED); + this.terminated(previous); + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + * Enabled force condition propagation + * Lifted jumps to return sites + */ + protected final void notifyFailed(Throwable cause) { + Preconditions.checkNotNull(cause); + this.monitor.enter(); + try { + Service.State previous = this.state(); + switch (previous) { + case NEW: + case TERMINATED: { + String string = String.valueOf(String.valueOf((Object)previous)); + throw new IllegalStateException(new StringBuilder(22 + string.length()).append("Failed while in state:").append(string).toString(), cause); + } + case STARTING: + case RUNNING: + case STOPPING: { + this.snapshot = new StateSnapshot(Service.State.FAILED, false, cause); + this.failed(previous, cause); + return; + } + case FAILED: { + return; + } + default: { + String string = String.valueOf(String.valueOf((Object)previous)); + throw new AssertionError((Object)new StringBuilder(18 + string.length()).append("Unexpected state: ").append(string).toString()); + } + } + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } + + @Override + public final boolean isRunning() { + return this.state() == Service.State.RUNNING; + } + + @Override + public final Service.State state() { + return this.snapshot.externalState(); + } + + @Override + public final Throwable failureCause() { + return this.snapshot.failureCause(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public final void addListener(Service.Listener listener, Executor executor) { + Preconditions.checkNotNull(listener, "listener"); + Preconditions.checkNotNull(executor, "executor"); + this.monitor.enter(); + try { + if (!this.state().isTerminal()) { + this.listeners.add(new ListenerCallQueue(listener, executor)); + } + } + finally { + this.monitor.leave(); + } + } + + public String toString() { + String string = String.valueOf(String.valueOf(this.getClass().getSimpleName())); + String string2 = String.valueOf(String.valueOf((Object)this.state())); + return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString(); + } + + private void executeListeners() { + if (!this.monitor.isOccupiedByCurrentThread()) { + for (int i = 0; i < this.listeners.size(); ++i) { + this.listeners.get(i).execute(); + } + } + } + + @GuardedBy(value="monitor") + private void starting() { + STARTING_CALLBACK.enqueueOn(this.listeners); + } + + @GuardedBy(value="monitor") + private void running() { + RUNNING_CALLBACK.enqueueOn(this.listeners); + } + + @GuardedBy(value="monitor") + private void stopping(Service.State from) { + if (from == Service.State.STARTING) { + STOPPING_FROM_STARTING_CALLBACK.enqueueOn(this.listeners); + } else if (from == Service.State.RUNNING) { + STOPPING_FROM_RUNNING_CALLBACK.enqueueOn(this.listeners); + } else { + throw new AssertionError(); + } + } + + @GuardedBy(value="monitor") + private void terminated(Service.State from) { + switch (from) { + case NEW: { + TERMINATED_FROM_NEW_CALLBACK.enqueueOn(this.listeners); + break; + } + case RUNNING: { + TERMINATED_FROM_RUNNING_CALLBACK.enqueueOn(this.listeners); + break; + } + case STOPPING: { + TERMINATED_FROM_STOPPING_CALLBACK.enqueueOn(this.listeners); + break; + } + default: { + throw new AssertionError(); + } + } + } + + @GuardedBy(value="monitor") + private void failed(final Service.State from, final Throwable cause) { + String string = String.valueOf(String.valueOf((Object)from)); + String string2 = String.valueOf(String.valueOf(cause)); + new ListenerCallQueue.Callback(new StringBuilder(27 + string.length() + string2.length()).append("failed({from = ").append(string).append(", cause = ").append(string2).append("})").toString()){ + + @Override + void call(Service.Listener listener) { + listener.failed(from, cause); + } + }.enqueueOn(this.listeners); + } + + @Immutable + private static final class StateSnapshot { + final Service.State state; + final boolean shutdownWhenStartupFinishes; + @Nullable + final Throwable failure; + + StateSnapshot(Service.State internalState) { + this(internalState, false, null); + } + + StateSnapshot(Service.State internalState, boolean shutdownWhenStartupFinishes, @Nullable Throwable failure) { + Preconditions.checkArgument(!shutdownWhenStartupFinishes || internalState == Service.State.STARTING, "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.", new Object[]{internalState}); + Preconditions.checkArgument(!(failure != null ^ internalState == Service.State.FAILED), "A failure cause should be set if and only if the state is failed. Got %s and %s instead.", new Object[]{internalState, failure}); + this.state = internalState; + this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes; + this.failure = failure; + } + + Service.State externalState() { + if (this.shutdownWhenStartupFinishes && this.state == Service.State.STARTING) { + return Service.State.STOPPING; + } + return this.state; + } + + Throwable failureCause() { + Preconditions.checkState(this.state == Service.State.FAILED, "failureCause() is only valid if the service has failed, service is %s", new Object[]{this.state}); + return this.failure; + } + } +} diff --git a/src/com/google/common/util/concurrent/AsyncFunction.java b/src/com/google/common/util/concurrent/AsyncFunction.java new file mode 100644 index 0000000..34de7bd --- /dev/null +++ b/src/com/google/common/util/concurrent/AsyncFunction.java @@ -0,0 +1,10 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.ListenableFuture; + +public interface AsyncFunction { + public ListenableFuture apply(I var1) throws Exception; +} diff --git a/src/com/google/common/util/concurrent/AsyncSettableFuture.java b/src/com/google/common/util/concurrent/AsyncSettableFuture.java new file mode 100644 index 0000000..967e4c1 --- /dev/null +++ b/src/com/google/common/util/concurrent/AsyncSettableFuture.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.ForwardingListenableFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nullable; + +final class AsyncSettableFuture +extends ForwardingListenableFuture { + private final NestedFuture nested = new NestedFuture(); + private final ListenableFuture dereferenced = Futures.dereference(this.nested); + + public static AsyncSettableFuture create() { + return new AsyncSettableFuture(); + } + + private AsyncSettableFuture() { + } + + @Override + protected ListenableFuture delegate() { + return this.dereferenced; + } + + public boolean setFuture(ListenableFuture future) { + return this.nested.setFuture(Preconditions.checkNotNull(future)); + } + + public boolean setValue(@Nullable V value) { + return this.setFuture(Futures.immediateFuture(value)); + } + + public boolean setException(Throwable exception) { + return this.setFuture(Futures.immediateFailedFuture(exception)); + } + + public boolean isSet() { + return this.nested.isDone(); + } + + private static final class NestedFuture + extends AbstractFuture> { + private NestedFuture() { + } + + boolean setFuture(ListenableFuture value) { + boolean result = this.set(value); + if (this.isCancelled()) { + value.cancel(this.wasInterrupted()); + } + return result; + } + } +} diff --git a/src/com/google/common/util/concurrent/AtomicDouble.java b/src/com/google/common/util/concurrent/AtomicDouble.java new file mode 100644 index 0000000..c54e441 --- /dev/null +++ b/src/com/google/common/util/concurrent/AtomicDouble.java @@ -0,0 +1,105 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; + +public class AtomicDouble +extends Number +implements Serializable { + private static final long serialVersionUID = 0L; + private volatile transient long value; + private static final AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value"); + + public AtomicDouble(double initialValue) { + this.value = Double.doubleToRawLongBits(initialValue); + } + + public AtomicDouble() { + } + + public final double get() { + return Double.longBitsToDouble(this.value); + } + + public final void set(double newValue) { + long next; + this.value = next = Double.doubleToRawLongBits(newValue); + } + + public final void lazySet(double newValue) { + this.set(newValue); + } + + public final double getAndSet(double newValue) { + long next = Double.doubleToRawLongBits(newValue); + return Double.longBitsToDouble(updater.getAndSet(this, next)); + } + + public final boolean compareAndSet(double expect, double update) { + return updater.compareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + public final boolean weakCompareAndSet(double expect, double update) { + return updater.weakCompareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + public final double getAndAdd(double delta) { + double currentVal; + double nextVal; + long next; + long current; + while (!updater.compareAndSet(this, current = this.value, next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) { + } + return currentVal; + } + + public final double addAndGet(double delta) { + double currentVal; + double nextVal; + long next; + long current; + while (!updater.compareAndSet(this, current = this.value, next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) { + } + return nextVal; + } + + public String toString() { + return Double.toString(this.get()); + } + + @Override + public int intValue() { + return (int)this.get(); + } + + @Override + public long longValue() { + return (long)this.get(); + } + + @Override + public float floatValue() { + return (float)this.get(); + } + + @Override + public double doubleValue() { + return this.get(); + } + + private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); + s.writeDouble(this.get()); + } + + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + this.set(s.readDouble()); + } +} diff --git a/src/com/google/common/util/concurrent/AtomicDoubleArray.java b/src/com/google/common/util/concurrent/AtomicDoubleArray.java new file mode 100644 index 0000000..3b9aa4e --- /dev/null +++ b/src/com/google/common/util/concurrent/AtomicDoubleArray.java @@ -0,0 +1,115 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicLongArray; + +public class AtomicDoubleArray +implements Serializable { + private static final long serialVersionUID = 0L; + private transient AtomicLongArray longs; + + public AtomicDoubleArray(int length) { + this.longs = new AtomicLongArray(length); + } + + public AtomicDoubleArray(double[] array) { + int len = array.length; + long[] longArray = new long[len]; + for (int i = 0; i < len; ++i) { + longArray[i] = Double.doubleToRawLongBits(array[i]); + } + this.longs = new AtomicLongArray(longArray); + } + + public final int length() { + return this.longs.length(); + } + + public final double get(int i) { + return Double.longBitsToDouble(this.longs.get(i)); + } + + public final void set(int i, double newValue) { + long next = Double.doubleToRawLongBits(newValue); + this.longs.set(i, next); + } + + public final void lazySet(int i, double newValue) { + this.set(i, newValue); + } + + public final double getAndSet(int i, double newValue) { + long next = Double.doubleToRawLongBits(newValue); + return Double.longBitsToDouble(this.longs.getAndSet(i, next)); + } + + public final boolean compareAndSet(int i, double expect, double update) { + return this.longs.compareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + public final boolean weakCompareAndSet(int i, double expect, double update) { + return this.longs.weakCompareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + public final double getAndAdd(int i, double delta) { + double currentVal; + double nextVal; + long next; + long current; + while (!this.longs.compareAndSet(i, current = this.longs.get(i), next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) { + } + return currentVal; + } + + public double addAndGet(int i, double delta) { + double currentVal; + double nextVal; + long next; + long current; + while (!this.longs.compareAndSet(i, current = this.longs.get(i), next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) { + } + return nextVal; + } + + public String toString() { + int iMax = this.length() - 1; + if (iMax == -1) { + return "[]"; + } + StringBuilder b = new StringBuilder(19 * (iMax + 1)); + b.append('['); + int i = 0; + while (true) { + b.append(Double.longBitsToDouble(this.longs.get(i))); + if (i == iMax) { + return b.append(']').toString(); + } + b.append(',').append(' '); + ++i; + } + } + + private void writeObject(ObjectOutputStream s) throws IOException { + s.defaultWriteObject(); + int length = this.length(); + s.writeInt(length); + for (int i = 0; i < length; ++i) { + s.writeDouble(this.get(i)); + } + } + + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + s.defaultReadObject(); + int length = s.readInt(); + this.longs = new AtomicLongArray(length); + for (int i = 0; i < length; ++i) { + this.set(i, s.readDouble()); + } + } +} diff --git a/src/com/google/common/util/concurrent/AtomicLongMap.java b/src/com/google/common/util/concurrent/AtomicLongMap.java new file mode 100644 index 0000000..3512d48 --- /dev/null +++ b/src/com/google/common/util/concurrent/AtomicLongMap.java @@ -0,0 +1,216 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +@GwtCompatible +public final class AtomicLongMap { + private final ConcurrentHashMap map; + private transient Map asMap; + + private AtomicLongMap(ConcurrentHashMap map) { + this.map = Preconditions.checkNotNull(map); + } + + public static AtomicLongMap create() { + return new AtomicLongMap(new ConcurrentHashMap()); + } + + public static AtomicLongMap create(Map m) { + AtomicLongMap result = AtomicLongMap.create(); + result.putAll(m); + return result; + } + + public long get(K key) { + AtomicLong atomic = this.map.get(key); + return atomic == null ? 0L : atomic.get(); + } + + public long incrementAndGet(K key) { + return this.addAndGet(key, 1L); + } + + public long decrementAndGet(K key) { + return this.addAndGet(key, -1L); + } + + public long addAndGet(K key, long delta) { + long newValue; + block0: while (true) { + long oldValue; + AtomicLong atomic; + if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(delta))) == null) { + return delta; + } + do { + if ((oldValue = atomic.get()) != 0L) continue; + if (!this.map.replace(key, atomic, new AtomicLong(delta))) continue block0; + return delta; + } while (!atomic.compareAndSet(oldValue, newValue = oldValue + delta)); + break; + } + return newValue; + } + + public long getAndIncrement(K key) { + return this.getAndAdd(key, 1L); + } + + public long getAndDecrement(K key) { + return this.getAndAdd(key, -1L); + } + + public long getAndAdd(K key, long delta) { + long oldValue; + block0: while (true) { + long newValue; + AtomicLong atomic; + if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(delta))) == null) { + return 0L; + } + do { + if ((oldValue = atomic.get()) != 0L) continue; + if (!this.map.replace(key, atomic, new AtomicLong(delta))) continue block0; + return 0L; + } while (!atomic.compareAndSet(oldValue, newValue = oldValue + delta)); + break; + } + return oldValue; + } + + public long put(K key, long newValue) { + long oldValue; + block0: while (true) { + AtomicLong atomic; + if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(newValue))) == null) { + return 0L; + } + do { + if ((oldValue = atomic.get()) != 0L) continue; + if (!this.map.replace(key, atomic, new AtomicLong(newValue))) continue block0; + return 0L; + } while (!atomic.compareAndSet(oldValue, newValue)); + break; + } + return oldValue; + } + + public void putAll(Map m) { + for (Map.Entry entry : m.entrySet()) { + this.put(entry.getKey(), entry.getValue()); + } + } + + public long remove(K key) { + long oldValue; + AtomicLong atomic = this.map.get(key); + if (atomic == null) { + return 0L; + } + while ((oldValue = atomic.get()) != 0L && !atomic.compareAndSet(oldValue, 0L)) { + } + this.map.remove(key, atomic); + return oldValue; + } + + public void removeAllZeros() { + for (Object key : this.map.keySet()) { + AtomicLong atomic = this.map.get(key); + if (atomic == null || atomic.get() != 0L) continue; + this.map.remove(key, atomic); + } + } + + public long sum() { + long sum = 0L; + for (AtomicLong value : this.map.values()) { + sum += value.get(); + } + return sum; + } + + public Map asMap() { + Map result = this.asMap; + return result == null ? (this.asMap = this.createAsMap()) : result; + } + + private Map createAsMap() { + return Collections.unmodifiableMap(Maps.transformValues(this.map, new Function(){ + + @Override + public Long apply(AtomicLong atomic) { + return atomic.get(); + } + })); + } + + public boolean containsKey(Object key) { + return this.map.containsKey(key); + } + + public int size() { + return this.map.size(); + } + + public boolean isEmpty() { + return this.map.isEmpty(); + } + + public void clear() { + this.map.clear(); + } + + public String toString() { + return this.map.toString(); + } + + long putIfAbsent(K key, long newValue) { + long oldValue; + block2: { + AtomicLong atomic; + do { + if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(newValue))) == null) { + return 0L; + } + oldValue = atomic.get(); + if (oldValue != 0L) break block2; + } while (!this.map.replace(key, atomic, new AtomicLong(newValue))); + return 0L; + } + return oldValue; + } + + boolean replace(K key, long expectedOldValue, long newValue) { + if (expectedOldValue == 0L) { + return this.putIfAbsent(key, newValue) == 0L; + } + AtomicLong atomic = this.map.get(key); + return atomic == null ? false : atomic.compareAndSet(expectedOldValue, newValue); + } + + boolean remove(K key, long value) { + AtomicLong atomic = this.map.get(key); + if (atomic == null) { + return false; + } + long oldValue = atomic.get(); + if (oldValue != value) { + return false; + } + if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) { + this.map.remove(key, atomic); + return true; + } + return false; + } +} diff --git a/src/com/google/common/util/concurrent/Atomics.java b/src/com/google/common/util/concurrent/Atomics.java new file mode 100644 index 0000000..e858fcd --- /dev/null +++ b/src/com/google/common/util/concurrent/Atomics.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceArray; +import javax.annotation.Nullable; + +public final class Atomics { + private Atomics() { + } + + public static AtomicReference newReference() { + return new AtomicReference(); + } + + public static AtomicReference newReference(@Nullable V initialValue) { + return new AtomicReference(initialValue); + } + + public static AtomicReferenceArray newReferenceArray(int length) { + return new AtomicReferenceArray(length); + } + + public static AtomicReferenceArray newReferenceArray(E[] array) { + return new AtomicReferenceArray(array); + } +} diff --git a/src/com/google/common/util/concurrent/Callables.java b/src/com/google/common/util/concurrent/Callables.java new file mode 100644 index 0000000..99e4c67 --- /dev/null +++ b/src/com/google/common/util/concurrent/Callables.java @@ -0,0 +1,85 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.concurrent.Callable; +import javax.annotation.Nullable; + +public final class Callables { + private Callables() { + } + + public static Callable returning(final @Nullable T value) { + return new Callable(){ + + @Override + public T call() { + return value; + } + }; + } + + static Callable threadRenaming(final Callable callable, final Supplier nameSupplier) { + Preconditions.checkNotNull(nameSupplier); + Preconditions.checkNotNull(callable); + return new Callable(){ + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public T call() throws Exception { + Thread currentThread = Thread.currentThread(); + String oldName = currentThread.getName(); + boolean restoreName = Callables.trySetName((String)nameSupplier.get(), currentThread); + try { + Object v = callable.call(); + return v; + } + finally { + if (restoreName) { + Callables.trySetName(oldName, currentThread); + } + } + } + }; + } + + static Runnable threadRenaming(final Runnable task, final Supplier nameSupplier) { + Preconditions.checkNotNull(nameSupplier); + Preconditions.checkNotNull(task); + return new Runnable(){ + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void run() { + Thread currentThread = Thread.currentThread(); + String oldName = currentThread.getName(); + boolean restoreName = Callables.trySetName((String)nameSupplier.get(), currentThread); + try { + task.run(); + } + finally { + if (restoreName) { + Callables.trySetName(oldName, currentThread); + } + } + } + }; + } + + private static boolean trySetName(String threadName, Thread currentThread) { + try { + currentThread.setName(threadName); + return true; + } + catch (SecurityException e) { + return false; + } + } +} diff --git a/src/com/google/common/util/concurrent/CheckedFuture.java b/src/com/google/common/util/concurrent/CheckedFuture.java new file mode 100644 index 0000000..92cc8ac --- /dev/null +++ b/src/com/google/common/util/concurrent/CheckedFuture.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public interface CheckedFuture +extends ListenableFuture { + public V checkedGet() throws X; + + public V checkedGet(long var1, TimeUnit var3) throws TimeoutException, X; +} diff --git a/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java new file mode 100644 index 0000000..b5fa837 --- /dev/null +++ b/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java @@ -0,0 +1,603 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.ThreadSafe; + +@Beta +@ThreadSafe +public class CycleDetectingLockFactory { + private static final ConcurrentMap, Map> lockGraphNodesPerType = new MapMaker().weakKeys().makeMap(); + private static final Logger logger = Logger.getLogger(CycleDetectingLockFactory.class.getName()); + final Policy policy; + private static final ThreadLocal> acquiredLocks = new ThreadLocal>(){ + + @Override + protected ArrayList initialValue() { + return Lists.newArrayListWithCapacity(3); + } + }; + + public static CycleDetectingLockFactory newInstance(Policy policy) { + return new CycleDetectingLockFactory(policy); + } + + public ReentrantLock newReentrantLock(String lockName) { + return this.newReentrantLock(lockName, false); + } + + public ReentrantLock newReentrantLock(String lockName, boolean fair) { + return this.policy == Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingReentrantLock(new LockGraphNode(lockName), fair); + } + + public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName) { + return this.newReentrantReadWriteLock(lockName, false); + } + + public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName, boolean fair) { + return this.policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingReentrantReadWriteLock(new LockGraphNode(lockName), fair); + } + + public static > WithExplicitOrdering newInstanceWithExplicitOrdering(Class enumClass, Policy policy) { + Preconditions.checkNotNull(enumClass); + Preconditions.checkNotNull(policy); + Map lockGraphNodes = CycleDetectingLockFactory.getOrCreateNodes(enumClass); + return new WithExplicitOrdering(policy, lockGraphNodes); + } + + private static Map getOrCreateNodes(Class clazz) { + Map existing = (Map)lockGraphNodesPerType.get(clazz); + if (existing != null) { + return existing; + } + Map created = CycleDetectingLockFactory.createNodes(clazz); + existing = lockGraphNodesPerType.putIfAbsent(clazz, created); + return MoreObjects.firstNonNull(existing, created); + } + + @VisibleForTesting + static > Map createNodes(Class clazz) { + int i; + EnumMap map = Maps.newEnumMap(clazz); + Enum[] keys = (Enum[])clazz.getEnumConstants(); + int numKeys = keys.length; + ArrayList nodes = Lists.newArrayListWithCapacity(numKeys); + for (Enum key : keys) { + LockGraphNode node = new LockGraphNode(CycleDetectingLockFactory.getLockName(key)); + nodes.add(node); + map.put(key, node); + } + for (i = 1; i < numKeys; ++i) { + ((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.THROW, nodes.subList(0, i)); + } + for (i = 0; i < numKeys - 1; ++i) { + ((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.DISABLED, nodes.subList(i + 1, numKeys)); + } + return Collections.unmodifiableMap(map); + } + + private static String getLockName(Enum rank) { + String string = String.valueOf(String.valueOf(rank.getDeclaringClass().getSimpleName())); + String string2 = String.valueOf(String.valueOf(rank.name())); + return new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString(); + } + + private CycleDetectingLockFactory(Policy policy) { + this.policy = Preconditions.checkNotNull(policy); + } + + private void aboutToAcquire(CycleDetectingLock lock) { + if (!lock.isAcquiredByCurrentThread()) { + ArrayList acquiredLockList = acquiredLocks.get(); + LockGraphNode node = lock.getLockGraphNode(); + node.checkAcquiredLocks(this.policy, acquiredLockList); + acquiredLockList.add(node); + } + } + + private void lockStateChanged(CycleDetectingLock lock) { + if (!lock.isAcquiredByCurrentThread()) { + ArrayList acquiredLockList = acquiredLocks.get(); + LockGraphNode node = lock.getLockGraphNode(); + for (int i = acquiredLockList.size() - 1; i >= 0; --i) { + if (acquiredLockList.get(i) != node) continue; + acquiredLockList.remove(i); + break; + } + } + } + + private class CycleDetectingReentrantWriteLock + extends ReentrantReadWriteLock.WriteLock { + final CycleDetectingReentrantReadWriteLock readWriteLock; + + CycleDetectingReentrantWriteLock(CycleDetectingReentrantReadWriteLock readWriteLock) { + super(readWriteLock); + this.readWriteLock = readWriteLock; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lock() { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + super.lock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lockInterruptibly() throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + super.lockInterruptibly(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock() { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + boolean bl = super.tryLock(); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + boolean bl = super.tryLock(timeout, unit); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void unlock() { + try { + super.unlock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + } + + private class CycleDetectingReentrantReadLock + extends ReentrantReadWriteLock.ReadLock { + final CycleDetectingReentrantReadWriteLock readWriteLock; + + CycleDetectingReentrantReadLock(CycleDetectingReentrantReadWriteLock readWriteLock) { + super(readWriteLock); + this.readWriteLock = readWriteLock; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lock() { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + super.lock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lockInterruptibly() throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + super.lockInterruptibly(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock() { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + boolean bl = super.tryLock(); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock); + try { + boolean bl = super.tryLock(timeout, unit); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void unlock() { + try { + super.unlock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock); + } + } + } + + final class CycleDetectingReentrantReadWriteLock + extends ReentrantReadWriteLock + implements CycleDetectingLock { + private final CycleDetectingReentrantReadLock readLock; + private final CycleDetectingReentrantWriteLock writeLock; + private final LockGraphNode lockGraphNode; + + private CycleDetectingReentrantReadWriteLock(LockGraphNode lockGraphNode, boolean fair) { + super(fair); + this.readLock = new CycleDetectingReentrantReadLock(this); + this.writeLock = new CycleDetectingReentrantWriteLock(this); + this.lockGraphNode = Preconditions.checkNotNull(lockGraphNode); + } + + @Override + public ReentrantReadWriteLock.ReadLock readLock() { + return this.readLock; + } + + @Override + public ReentrantReadWriteLock.WriteLock writeLock() { + return this.writeLock; + } + + @Override + public LockGraphNode getLockGraphNode() { + return this.lockGraphNode; + } + + @Override + public boolean isAcquiredByCurrentThread() { + return this.isWriteLockedByCurrentThread() || this.getReadHoldCount() > 0; + } + } + + final class CycleDetectingReentrantLock + extends ReentrantLock + implements CycleDetectingLock { + private final LockGraphNode lockGraphNode; + + private CycleDetectingReentrantLock(LockGraphNode lockGraphNode, boolean fair) { + super(fair); + this.lockGraphNode = Preconditions.checkNotNull(lockGraphNode); + } + + @Override + public LockGraphNode getLockGraphNode() { + return this.lockGraphNode; + } + + @Override + public boolean isAcquiredByCurrentThread() { + return this.isHeldByCurrentThread(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lock() { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + super.lock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void lockInterruptibly() throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + super.lockInterruptibly(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock() { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + boolean bl = super.tryLock(); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + boolean bl = super.tryLock(timeout, unit); + return bl; + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void unlock() { + try { + super.unlock(); + } + finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + } + + private static class LockGraphNode { + final Map allowedPriorLocks = new MapMaker().weakKeys().makeMap(); + final Map disallowedPriorLocks = new MapMaker().weakKeys().makeMap(); + final String lockName; + + LockGraphNode(String lockName) { + this.lockName = Preconditions.checkNotNull(lockName); + } + + String getLockName() { + return this.lockName; + } + + void checkAcquiredLocks(Policy policy, List acquiredLocks) { + int size = acquiredLocks.size(); + for (int i = 0; i < size; ++i) { + this.checkAcquiredLock(policy, acquiredLocks.get(i)); + } + } + + void checkAcquiredLock(Policy policy, LockGraphNode acquiredLock) { + String string = String.valueOf(acquiredLock.getLockName()); + Preconditions.checkState(this != acquiredLock, string.length() != 0 ? "Attempted to acquire multiple locks with the same rank ".concat(string) : new String("Attempted to acquire multiple locks with the same rank ")); + if (this.allowedPriorLocks.containsKey(acquiredLock)) { + return; + } + PotentialDeadlockException previousDeadlockException = this.disallowedPriorLocks.get(acquiredLock); + if (previousDeadlockException != null) { + PotentialDeadlockException exception = new PotentialDeadlockException(acquiredLock, this, previousDeadlockException.getConflictingStackTrace()); + policy.handlePotentialDeadlock(exception); + return; + } + Set seen = Sets.newIdentityHashSet(); + ExampleStackTrace path = acquiredLock.findPathTo(this, seen); + if (path == null) { + this.allowedPriorLocks.put(acquiredLock, new ExampleStackTrace(acquiredLock, this)); + } else { + PotentialDeadlockException exception = new PotentialDeadlockException(acquiredLock, this, path); + this.disallowedPriorLocks.put(acquiredLock, exception); + policy.handlePotentialDeadlock(exception); + } + } + + @Nullable + private ExampleStackTrace findPathTo(LockGraphNode node, Set seen) { + if (!seen.add(this)) { + return null; + } + ExampleStackTrace found = this.allowedPriorLocks.get(node); + if (found != null) { + return found; + } + for (Map.Entry entry : this.allowedPriorLocks.entrySet()) { + LockGraphNode preAcquiredLock = entry.getKey(); + found = preAcquiredLock.findPathTo(node, seen); + if (found == null) continue; + ExampleStackTrace path = new ExampleStackTrace(preAcquiredLock, this); + path.setStackTrace(entry.getValue().getStackTrace()); + path.initCause(found); + return path; + } + return null; + } + } + + private static interface CycleDetectingLock { + public LockGraphNode getLockGraphNode(); + + public boolean isAcquiredByCurrentThread(); + } + + @Beta + public static final class PotentialDeadlockException + extends ExampleStackTrace { + private final ExampleStackTrace conflictingStackTrace; + + private PotentialDeadlockException(LockGraphNode node1, LockGraphNode node2, ExampleStackTrace conflictingStackTrace) { + super(node1, node2); + this.conflictingStackTrace = conflictingStackTrace; + this.initCause(conflictingStackTrace); + } + + public ExampleStackTrace getConflictingStackTrace() { + return this.conflictingStackTrace; + } + + @Override + public String getMessage() { + StringBuilder message = new StringBuilder(super.getMessage()); + for (Throwable t = this.conflictingStackTrace; t != null; t = t.getCause()) { + message.append(", ").append(t.getMessage()); + } + return message.toString(); + } + } + + private static class ExampleStackTrace + extends IllegalStateException { + static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; + static Set EXCLUDED_CLASS_NAMES = ImmutableSet.of(CycleDetectingLockFactory.class.getName(), ExampleStackTrace.class.getName(), LockGraphNode.class.getName()); + + ExampleStackTrace(LockGraphNode node1, LockGraphNode node2) { + String string = String.valueOf(String.valueOf(node1.getLockName())); + String string2 = String.valueOf(String.valueOf(node2.getLockName())); + super(new StringBuilder(4 + string.length() + string2.length()).append(string).append(" -> ").append(string2).toString()); + StackTraceElement[] origStackTrace = this.getStackTrace(); + int n = origStackTrace.length; + for (int i = 0; i < n; ++i) { + if (WithExplicitOrdering.class.getName().equals(origStackTrace[i].getClassName())) { + this.setStackTrace(EMPTY_STACK_TRACE); + break; + } + if (EXCLUDED_CLASS_NAMES.contains(origStackTrace[i].getClassName())) continue; + this.setStackTrace(Arrays.copyOfRange(origStackTrace, i, n)); + break; + } + } + } + + @Beta + public static final class WithExplicitOrdering> + extends CycleDetectingLockFactory { + private final Map lockGraphNodes; + + @VisibleForTesting + WithExplicitOrdering(Policy policy, Map lockGraphNodes) { + super(policy); + this.lockGraphNodes = lockGraphNodes; + } + + public ReentrantLock newReentrantLock(E rank) { + return this.newReentrantLock(rank, false); + } + + public ReentrantLock newReentrantLock(E rank, boolean fair) { + return this.policy == Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingReentrantLock(this.lockGraphNodes.get(rank), fair); + } + + public ReentrantReadWriteLock newReentrantReadWriteLock(E rank) { + return this.newReentrantReadWriteLock(rank, false); + } + + public ReentrantReadWriteLock newReentrantReadWriteLock(E rank, boolean fair) { + return this.policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingReentrantReadWriteLock(this.lockGraphNodes.get(rank), fair); + } + } + + @Beta + public static enum Policies implements Policy + { + THROW{ + + @Override + public void handlePotentialDeadlock(PotentialDeadlockException e) { + throw e; + } + } + , + WARN{ + + @Override + public void handlePotentialDeadlock(PotentialDeadlockException e) { + logger.log(Level.SEVERE, "Detected potential deadlock", e); + } + } + , + DISABLED{ + + @Override + public void handlePotentialDeadlock(PotentialDeadlockException e) { + } + }; + + } + + @Beta + @ThreadSafe + public static interface Policy { + public void handlePotentialDeadlock(PotentialDeadlockException var1); + } +} diff --git a/src/com/google/common/util/concurrent/ExecutionError.java b/src/com/google/common/util/concurrent/ExecutionError.java new file mode 100644 index 0000000..ba73bb4 --- /dev/null +++ b/src/com/google/common/util/concurrent/ExecutionError.java @@ -0,0 +1,28 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public class ExecutionError +extends Error { + private static final long serialVersionUID = 0L; + + protected ExecutionError() { + } + + protected ExecutionError(@Nullable String message) { + super(message); + } + + public ExecutionError(@Nullable String message, @Nullable Error cause) { + super(message, cause); + } + + public ExecutionError(@Nullable Error cause) { + super(cause); + } +} diff --git a/src/com/google/common/util/concurrent/ExecutionList.java b/src/com/google/common/util/concurrent/ExecutionList.java new file mode 100644 index 0000000..f09e63b --- /dev/null +++ b/src/com/google/common/util/concurrent/ExecutionList.java @@ -0,0 +1,88 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + +public final class ExecutionList { + @VisibleForTesting + static final Logger log = Logger.getLogger(ExecutionList.class.getName()); + @GuardedBy(value="this") + private RunnableExecutorPair runnables; + @GuardedBy(value="this") + private boolean executed; + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void add(Runnable runnable, Executor executor) { + Preconditions.checkNotNull(runnable, "Runnable was null."); + Preconditions.checkNotNull(executor, "Executor was null."); + ExecutionList executionList = this; + synchronized (executionList) { + if (!this.executed) { + this.runnables = new RunnableExecutorPair(runnable, executor, this.runnables); + return; + } + } + ExecutionList.executeListener(runnable, executor); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void execute() { + RunnableExecutorPair list; + ExecutionList executionList = this; + synchronized (executionList) { + if (this.executed) { + return; + } + this.executed = true; + list = this.runnables; + this.runnables = null; + } + RunnableExecutorPair reversedList = null; + while (list != null) { + RunnableExecutorPair tmp = list; + list = list.next; + tmp.next = reversedList; + reversedList = tmp; + } + while (reversedList != null) { + ExecutionList.executeListener(reversedList.runnable, reversedList.executor); + reversedList = reversedList.next; + } + } + + private static void executeListener(Runnable runnable, Executor executor) { + try { + executor.execute(runnable); + } + catch (RuntimeException e) { + String string = String.valueOf(String.valueOf(runnable)); + String string2 = String.valueOf(String.valueOf(executor)); + log.log(Level.SEVERE, new StringBuilder(57 + string.length() + string2.length()).append("RuntimeException while executing runnable ").append(string).append(" with executor ").append(string2).toString(), e); + } + } + + private static final class RunnableExecutorPair { + final Runnable runnable; + final Executor executor; + @Nullable + RunnableExecutorPair next; + + RunnableExecutorPair(Runnable runnable, Executor executor, RunnableExecutorPair next) { + this.runnable = runnable; + this.executor = executor; + this.next = next; + } + } +} diff --git a/src/com/google/common/util/concurrent/FakeTimeLimiter.java b/src/com/google/common/util/concurrent/FakeTimeLimiter.java new file mode 100644 index 0000000..91910d9 --- /dev/null +++ b/src/com/google/common/util/concurrent/FakeTimeLimiter.java @@ -0,0 +1,28 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.TimeLimiter; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +@Beta +public final class FakeTimeLimiter +implements TimeLimiter { + @Override + public T newProxy(T target, Class interfaceType, long timeoutDuration, TimeUnit timeoutUnit) { + Preconditions.checkNotNull(target); + Preconditions.checkNotNull(interfaceType); + Preconditions.checkNotNull(timeoutUnit); + return target; + } + + @Override + public T callWithTimeout(Callable callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { + Preconditions.checkNotNull(timeoutUnit); + return callable.call(); + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java b/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java new file mode 100644 index 0000000..a513d2a --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.collect.ForwardingQueue; +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; + +public abstract class ForwardingBlockingQueue +extends ForwardingQueue +implements BlockingQueue { + protected ForwardingBlockingQueue() { + } + + @Override + protected abstract BlockingQueue delegate(); + + @Override + public int drainTo(Collection c, int maxElements) { + return this.delegate().drainTo(c, maxElements); + } + + @Override + public int drainTo(Collection c) { + return this.delegate().drainTo(c); + } + + @Override + public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().offer(e, timeout, unit); + } + + @Override + public E poll(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().poll(timeout, unit); + } + + @Override + public void put(E e) throws InterruptedException { + this.delegate().put(e); + } + + @Override + public int remainingCapacity() { + return this.delegate().remainingCapacity(); + } + + @Override + public E take() throws InterruptedException { + return this.delegate().take(); + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java b/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java new file mode 100644 index 0000000..2f0466c --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java @@ -0,0 +1,44 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ForwardingListenableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public abstract class ForwardingCheckedFuture +extends ForwardingListenableFuture +implements CheckedFuture { + @Override + public V checkedGet() throws X { + return this.delegate().checkedGet(); + } + + @Override + public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X { + return this.delegate().checkedGet(timeout, unit); + } + + @Override + protected abstract CheckedFuture delegate(); + + @Beta + public static abstract class SimpleForwardingCheckedFuture + extends ForwardingCheckedFuture { + private final CheckedFuture delegate; + + protected SimpleForwardingCheckedFuture(CheckedFuture delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected final CheckedFuture delegate() { + return this.delegate; + } + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingExecutorService.java b/src/com/google/common/util/concurrent/ForwardingExecutorService.java new file mode 100644 index 0000000..fe6d648 --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingExecutorService.java @@ -0,0 +1,89 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.collect.ForwardingObject; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public abstract class ForwardingExecutorService +extends ForwardingObject +implements ExecutorService { + protected ForwardingExecutorService() { + } + + @Override + protected abstract ExecutorService delegate(); + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().awaitTermination(timeout, unit); + } + + @Override + public List> invokeAll(Collection> tasks) throws InterruptedException { + return this.delegate().invokeAll(tasks); + } + + @Override + public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate().invokeAll(tasks, timeout, unit); + } + + @Override + public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { + return this.delegate().invokeAny(tasks); + } + + @Override + public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return this.delegate().invokeAny(tasks, timeout, unit); + } + + @Override + public boolean isShutdown() { + return this.delegate().isShutdown(); + } + + @Override + public boolean isTerminated() { + return this.delegate().isTerminated(); + } + + @Override + public void shutdown() { + this.delegate().shutdown(); + } + + @Override + public List shutdownNow() { + return this.delegate().shutdownNow(); + } + + @Override + public void execute(Runnable command) { + this.delegate().execute(command); + } + + @Override + public Future submit(Callable task) { + return this.delegate().submit(task); + } + + @Override + public Future submit(Runnable task) { + return this.delegate().submit(task); + } + + @Override + public Future submit(Runnable task, T result) { + return this.delegate().submit(task, result); + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingFuture.java b/src/com/google/common/util/concurrent/ForwardingFuture.java new file mode 100644 index 0000000..1601f2b --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingFuture.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingObject; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public abstract class ForwardingFuture +extends ForwardingObject +implements Future { + protected ForwardingFuture() { + } + + @Override + protected abstract Future delegate(); + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return this.delegate().cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return this.delegate().isCancelled(); + } + + @Override + public boolean isDone() { + return this.delegate().isDone(); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + return this.delegate().get(); + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return this.delegate().get(timeout, unit); + } + + public static abstract class SimpleForwardingFuture + extends ForwardingFuture { + private final Future delegate; + + protected SimpleForwardingFuture(Future delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected final Future delegate() { + return this.delegate; + } + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingListenableFuture.java b/src/com/google/common/util/concurrent/ForwardingListenableFuture.java new file mode 100644 index 0000000..58d32fd --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingListenableFuture.java @@ -0,0 +1,38 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ForwardingFuture; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Executor; + +public abstract class ForwardingListenableFuture +extends ForwardingFuture +implements ListenableFuture { + protected ForwardingListenableFuture() { + } + + @Override + protected abstract ListenableFuture delegate(); + + @Override + public void addListener(Runnable listener, Executor exec) { + this.delegate().addListener(listener, exec); + } + + public static abstract class SimpleForwardingListenableFuture + extends ForwardingListenableFuture { + private final ListenableFuture delegate; + + protected SimpleForwardingListenableFuture(ListenableFuture delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + protected final ListenableFuture delegate() { + return this.delegate; + } + } +} diff --git a/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java b/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java new file mode 100644 index 0000000..ea6130f --- /dev/null +++ b/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java @@ -0,0 +1,34 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.ForwardingExecutorService; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import java.util.concurrent.Callable; + +public abstract class ForwardingListeningExecutorService +extends ForwardingExecutorService +implements ListeningExecutorService { + protected ForwardingListeningExecutorService() { + } + + @Override + protected abstract ListeningExecutorService delegate(); + + @Override + public ListenableFuture submit(Callable task) { + return this.delegate().submit(task); + } + + @Override + public ListenableFuture submit(Runnable task) { + return this.delegate().submit(task); + } + + @Override + public ListenableFuture submit(Runnable task, T result) { + return this.delegate().submit(task, result); + } +} diff --git a/src/com/google/common/util/concurrent/FutureCallback.java b/src/com/google/common/util/concurrent/FutureCallback.java new file mode 100644 index 0000000..2a5bda5 --- /dev/null +++ b/src/com/google/common/util/concurrent/FutureCallback.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import javax.annotation.Nullable; + +public interface FutureCallback { + public void onSuccess(@Nullable V var1); + + public void onFailure(Throwable var1); +} diff --git a/src/com/google/common/util/concurrent/FutureFallback.java b/src/com/google/common/util/concurrent/FutureFallback.java new file mode 100644 index 0000000..d00cfb0 --- /dev/null +++ b/src/com/google/common/util/concurrent/FutureFallback.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableFuture; + +@Beta +public interface FutureFallback { + public ListenableFuture create(Throwable var1) throws Exception; +} diff --git a/src/com/google/common/util/concurrent/Futures.java b/src/com/google/common/util/concurrent/Futures.java new file mode 100644 index 0000000..3d0bce9 --- /dev/null +++ b/src/com/google/common/util/concurrent/Futures.java @@ -0,0 +1,931 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import com.google.common.collect.Queues; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.AbstractCheckedFuture; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.AsyncSettableFuture; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ExecutionError; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.FutureFallback; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SerializingExecutor; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.common.util.concurrent.Uninterruptibles; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +@Beta +public final class Futures { + private static final AsyncFunction, Object> DEREFERENCER = new AsyncFunction, Object>(){ + + @Override + public ListenableFuture apply(ListenableFuture input) { + return input; + } + }; + private static final Ordering> WITH_STRING_PARAM_FIRST = Ordering.natural().onResultOf(new Function, Boolean>(){ + + @Override + public Boolean apply(Constructor input) { + return Arrays.asList(input.getParameterTypes()).contains(String.class); + } + }).reverse(); + + private Futures() { + } + + public static CheckedFuture makeChecked(ListenableFuture future, Function mapper) { + return new MappingCheckedFuture(Preconditions.checkNotNull(future), mapper); + } + + public static ListenableFuture immediateFuture(@Nullable V value) { + return new ImmediateSuccessfulFuture(value); + } + + public static CheckedFuture immediateCheckedFuture(@Nullable V value) { + return new ImmediateSuccessfulCheckedFuture(value); + } + + public static ListenableFuture immediateFailedFuture(Throwable throwable) { + Preconditions.checkNotNull(throwable); + return new ImmediateFailedFuture(throwable); + } + + public static ListenableFuture immediateCancelledFuture() { + return new ImmediateCancelledFuture(); + } + + public static CheckedFuture immediateFailedCheckedFuture(X exception) { + Preconditions.checkNotNull(exception); + return new ImmediateFailedCheckedFuture(exception); + } + + public static ListenableFuture withFallback(ListenableFuture input, FutureFallback fallback) { + return Futures.withFallback(input, fallback, MoreExecutors.directExecutor()); + } + + public static ListenableFuture withFallback(ListenableFuture input, FutureFallback fallback, Executor executor) { + Preconditions.checkNotNull(fallback); + return new FallbackFuture(input, fallback, executor); + } + + public static ListenableFuture transform(ListenableFuture input, AsyncFunction function) { + ChainingListenableFuture output = new ChainingListenableFuture(function, input); + input.addListener(output, MoreExecutors.directExecutor()); + return output; + } + + public static ListenableFuture transform(ListenableFuture input, AsyncFunction function, Executor executor) { + Preconditions.checkNotNull(executor); + ChainingListenableFuture output = new ChainingListenableFuture(function, input); + input.addListener(Futures.rejectionPropagatingRunnable(output, output, executor), MoreExecutors.directExecutor()); + return output; + } + + private static Runnable rejectionPropagatingRunnable(final AbstractFuture outputFuture, final Runnable delegateTask, final Executor delegateExecutor) { + return new Runnable(){ + + @Override + public void run() { + block2: { + final AtomicBoolean thrownFromDelegate = new AtomicBoolean(true); + try { + delegateExecutor.execute(new Runnable(){ + + @Override + public void run() { + thrownFromDelegate.set(false); + delegateTask.run(); + } + }); + } + catch (RejectedExecutionException e) { + if (!thrownFromDelegate.get()) break block2; + outputFuture.setException(e); + } + } + } + }; + } + + public static ListenableFuture transform(ListenableFuture input, Function function) { + Preconditions.checkNotNull(function); + ChainingListenableFuture output = new ChainingListenableFuture(Futures.asAsyncFunction(function), input); + input.addListener(output, MoreExecutors.directExecutor()); + return output; + } + + public static ListenableFuture transform(ListenableFuture input, Function function, Executor executor) { + Preconditions.checkNotNull(function); + return Futures.transform(input, Futures.asAsyncFunction(function), executor); + } + + private static AsyncFunction asAsyncFunction(final Function function) { + return new AsyncFunction(){ + + @Override + public ListenableFuture apply(I input) { + Object output = function.apply(input); + return Futures.immediateFuture(output); + } + }; + } + + public static Future lazyTransform(final Future input, final Function function) { + Preconditions.checkNotNull(input); + Preconditions.checkNotNull(function); + return new Future(){ + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return input.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return input.isCancelled(); + } + + @Override + public boolean isDone() { + return input.isDone(); + } + + @Override + public O get() throws InterruptedException, ExecutionException { + return this.applyTransformation(input.get()); + } + + @Override + public O get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return this.applyTransformation(input.get(timeout, unit)); + } + + private O applyTransformation(I input2) throws ExecutionException { + try { + return function.apply(input2); + } + catch (Throwable t) { + throw new ExecutionException(t); + } + } + }; + } + + public static ListenableFuture dereference(ListenableFuture> nested) { + return Futures.transform(nested, DEREFERENCER); + } + + @Beta + public static ListenableFuture> allAsList(ListenableFuture ... futures) { + return Futures.listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.directExecutor()); + } + + @Beta + public static ListenableFuture> allAsList(Iterable> futures) { + return Futures.listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.directExecutor()); + } + + public static ListenableFuture nonCancellationPropagating(ListenableFuture future) { + return new NonCancellationPropagatingFuture(future); + } + + @Beta + public static ListenableFuture> successfulAsList(ListenableFuture ... futures) { + return Futures.listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.directExecutor()); + } + + @Beta + public static ListenableFuture> successfulAsList(Iterable> futures) { + return Futures.listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.directExecutor()); + } + + @Beta + public static ImmutableList> inCompletionOrder(Iterable> futures) { + final ConcurrentLinkedQueue delegates = Queues.newConcurrentLinkedQueue(); + ImmutableList.Builder listBuilder = ImmutableList.builder(); + SerializingExecutor executor = new SerializingExecutor(MoreExecutors.directExecutor()); + for (final ListenableFuture future : futures) { + AsyncSettableFuture delegate = AsyncSettableFuture.create(); + delegates.add(delegate); + future.addListener(new Runnable(){ + + @Override + public void run() { + ((AsyncSettableFuture)delegates.remove()).setFuture(future); + } + }, executor); + listBuilder.add(delegate); + } + return listBuilder.build(); + } + + public static void addCallback(ListenableFuture future, FutureCallback callback) { + Futures.addCallback(future, callback, MoreExecutors.directExecutor()); + } + + public static void addCallback(final ListenableFuture future, final FutureCallback callback, Executor executor) { + Preconditions.checkNotNull(callback); + Runnable callbackListener = new Runnable(){ + + @Override + public void run() { + Object value; + try { + value = Uninterruptibles.getUninterruptibly(future); + } + catch (ExecutionException e) { + callback.onFailure(e.getCause()); + return; + } + catch (RuntimeException e) { + callback.onFailure(e); + return; + } + catch (Error e) { + callback.onFailure(e); + return; + } + callback.onSuccess(value); + } + }; + future.addListener(callbackListener, executor); + } + + public static V get(Future future, Class exceptionClass) throws X { + Preconditions.checkNotNull(future); + Preconditions.checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", exceptionClass); + try { + return future.get(); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw Futures.newWithCause(exceptionClass, e); + } + catch (ExecutionException e) { + Futures.wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); + throw new AssertionError(); + } + } + + public static V get(Future future, long timeout, TimeUnit unit, Class exceptionClass) throws X { + Preconditions.checkNotNull(future); + Preconditions.checkNotNull(unit); + Preconditions.checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", exceptionClass); + try { + return future.get(timeout, unit); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw Futures.newWithCause(exceptionClass, e); + } + catch (TimeoutException e) { + throw Futures.newWithCause(exceptionClass, e); + } + catch (ExecutionException e) { + Futures.wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); + throw new AssertionError(); + } + } + + private static void wrapAndThrowExceptionOrError(Throwable cause, Class exceptionClass) throws X { + if (cause instanceof Error) { + throw new ExecutionError((Error)cause); + } + if (cause instanceof RuntimeException) { + throw new UncheckedExecutionException(cause); + } + throw Futures.newWithCause(exceptionClass, cause); + } + + public static V getUnchecked(Future future) { + Preconditions.checkNotNull(future); + try { + return Uninterruptibles.getUninterruptibly(future); + } + catch (ExecutionException e) { + Futures.wrapAndThrowUnchecked(e.getCause()); + throw new AssertionError(); + } + } + + private static void wrapAndThrowUnchecked(Throwable cause) { + if (cause instanceof Error) { + throw new ExecutionError((Error)cause); + } + throw new UncheckedExecutionException(cause); + } + + private static X newWithCause(Class exceptionClass, Throwable cause) { + List> constructors = Arrays.asList(exceptionClass.getConstructors()); + for (Constructor constructor : Futures.preferringStrings(constructors)) { + Exception instance = (Exception)Futures.newFromConstructor(constructor, cause); + if (instance == null) continue; + if (instance.getCause() == null) { + instance.initCause(cause); + } + return (X)instance; + } + String string = String.valueOf(String.valueOf(exceptionClass)); + throw new IllegalArgumentException(new StringBuilder(82 + string.length()).append("No appropriate constructor for exception of type ").append(string).append(" in response to chained exception").toString(), cause); + } + + private static List> preferringStrings(List> constructors) { + return WITH_STRING_PARAM_FIRST.sortedCopy(constructors); + } + + @Nullable + private static X newFromConstructor(Constructor constructor, Throwable cause) { + Class[] paramTypes = constructor.getParameterTypes(); + Object[] params = new Object[paramTypes.length]; + for (int i = 0; i < paramTypes.length; ++i) { + Class paramType = paramTypes[i]; + if (paramType.equals(String.class)) { + params[i] = cause.toString(); + continue; + } + if (paramType.equals(Throwable.class)) { + params[i] = cause; + continue; + } + return null; + } + try { + return constructor.newInstance(params); + } + catch (IllegalArgumentException e) { + return null; + } + catch (InstantiationException e) { + return null; + } + catch (IllegalAccessException e) { + return null; + } + catch (InvocationTargetException e) { + return null; + } + } + + private static ListenableFuture> listFuture(ImmutableList> futures, boolean allMustSucceed, Executor listenerExecutor) { + return new CombinedFuture(futures, allMustSucceed, listenerExecutor, new FutureCombiner>(){ + + @Override + public List combine(List> values) { + ArrayList result = Lists.newArrayList(); + for (Optional element : values) { + result.add(element != null ? (Object)element.orNull() : null); + } + return Collections.unmodifiableList(result); + } + }); + } + + private static class MappingCheckedFuture + extends AbstractCheckedFuture { + final Function mapper; + + MappingCheckedFuture(ListenableFuture delegate, Function mapper) { + super(delegate); + this.mapper = Preconditions.checkNotNull(mapper); + } + + @Override + protected X mapException(Exception e) { + return (X)((Exception)this.mapper.apply(e)); + } + } + + private static class CombinedFuture + extends AbstractFuture { + private static final Logger logger = Logger.getLogger(CombinedFuture.class.getName()); + ImmutableCollection> futures; + final boolean allMustSucceed; + final AtomicInteger remaining; + FutureCombiner combiner; + List> values; + final Object seenExceptionsLock = new Object(); + Set seenExceptions; + + CombinedFuture(ImmutableCollection> futures, boolean allMustSucceed, Executor listenerExecutor, FutureCombiner combiner) { + this.futures = futures; + this.allMustSucceed = allMustSucceed; + this.remaining = new AtomicInteger(futures.size()); + this.combiner = combiner; + this.values = Lists.newArrayListWithCapacity(futures.size()); + this.init(listenerExecutor); + } + + protected void init(Executor listenerExecutor) { + int i; + this.addListener(new Runnable(){ + + @Override + public void run() { + if (CombinedFuture.this.isCancelled()) { + for (ListenableFuture listenableFuture : CombinedFuture.this.futures) { + listenableFuture.cancel(CombinedFuture.this.wasInterrupted()); + } + } + CombinedFuture.this.futures = null; + CombinedFuture.this.values = null; + CombinedFuture.this.combiner = null; + } + }, MoreExecutors.directExecutor()); + if (this.futures.isEmpty()) { + this.set(this.combiner.combine(ImmutableList.of())); + return; + } + for (i = 0; i < this.futures.size(); ++i) { + this.values.add(null); + } + i = 0; + for (final ListenableFuture listenableFuture : this.futures) { + final int index = i++; + listenableFuture.addListener(new Runnable(){ + + @Override + public void run() { + CombinedFuture.this.setOneValue(index, listenableFuture); + } + }, listenerExecutor); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private void setExceptionAndMaybeLog(Throwable throwable) { + boolean visibleFromOutputFuture = false; + boolean firstTimeSeeingThisException = true; + if (this.allMustSucceed) { + visibleFromOutputFuture = super.setException(throwable); + Object object = this.seenExceptionsLock; + synchronized (object) { + if (this.seenExceptions == null) { + this.seenExceptions = Sets.newHashSet(); + } + firstTimeSeeingThisException = this.seenExceptions.add(throwable); + } + } + if (throwable instanceof Error || this.allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException) { + logger.log(Level.SEVERE, "input future failed.", throwable); + } + } + + /* + * Exception decompiling + */ + private void setOneValue(int index, Future future) { + /* + * This method has failed to decompile. When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file. + * + * org.benf.cfr.reader.util.ConfusedCFRException: Started 2 blocks at once + * at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.getStartingBlocks(Op04StructuredStatement.java:412) + * at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.buildNestedBlocks(Op04StructuredStatement.java:487) + * at org.benf.cfr.reader.bytecode.analysis.opgraph.Op03SimpleStatement.createInitialStructuredBlock(Op03SimpleStatement.java:736) + * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:850) + * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:278) + * at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:201) + * at org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94) + * at org.benf.cfr.reader.entities.Method.analyse(Method.java:531) + * at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1055) + * at org.benf.cfr.reader.entities.ClassFile.analyseInnerClassesPass1(ClassFile.java:923) + * at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1035) + * at org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:942) + * at org.benf.cfr.reader.Driver.doClass(Driver.java:84) + * at org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:78) + * at org.benf.cfr.reader.Main.main(Main.java:54) + */ + throw new IllegalStateException("Decompilation failed"); + } + } + + private static interface FutureCombiner { + public C combine(List> var1); + } + + private static class NonCancellationPropagatingFuture + extends AbstractFuture { + NonCancellationPropagatingFuture(final ListenableFuture delegate) { + Preconditions.checkNotNull(delegate); + Futures.addCallback(delegate, new FutureCallback(){ + + @Override + public void onSuccess(V result) { + NonCancellationPropagatingFuture.this.set(result); + } + + @Override + public void onFailure(Throwable t) { + if (delegate.isCancelled()) { + NonCancellationPropagatingFuture.this.cancel(false); + } else { + NonCancellationPropagatingFuture.this.setException(t); + } + } + }, MoreExecutors.directExecutor()); + } + } + + private static final class CombinerFuture + extends ListenableFutureTask { + ImmutableList> futures; + + CombinerFuture(Callable callable, ImmutableList> futures) { + super(callable); + this.futures = futures; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + ImmutableList> futures = this.futures; + if (super.cancel(mayInterruptIfRunning)) { + for (ListenableFuture listenableFuture : futures) { + listenableFuture.cancel(mayInterruptIfRunning); + } + return true; + } + return false; + } + + @Override + protected void done() { + super.done(); + this.futures = null; + } + + @Override + protected void setException(Throwable t) { + super.setException(t); + } + } + + private static final class WrappedCombiner + implements Callable { + final Callable delegate; + CombinerFuture outputFuture; + + WrappedCombiner(Callable delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public T call() throws Exception { + try { + return this.delegate.call(); + } + catch (ExecutionException e) { + this.outputFuture.setException(e.getCause()); + } + catch (CancellationException e) { + this.outputFuture.cancel(false); + } + return null; + } + } + + private static class ChainingListenableFuture + extends AbstractFuture + implements Runnable { + private AsyncFunction function; + private ListenableFuture inputFuture; + private volatile ListenableFuture outputFuture; + + private ChainingListenableFuture(AsyncFunction function, ListenableFuture inputFuture) { + this.function = Preconditions.checkNotNull(function); + this.inputFuture = Preconditions.checkNotNull(inputFuture); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (super.cancel(mayInterruptIfRunning)) { + this.cancel(this.inputFuture, mayInterruptIfRunning); + this.cancel(this.outputFuture, mayInterruptIfRunning); + return true; + } + return false; + } + + private void cancel(@Nullable Future future, boolean mayInterruptIfRunning) { + if (future != null) { + future.cancel(mayInterruptIfRunning); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + * Loose catch block + */ + @Override + public void run() { + block14: { + try { + I sourceResult; + try { + sourceResult = Uninterruptibles.getUninterruptibly(this.inputFuture); + } + catch (CancellationException e) { + this.cancel(false); + this.function = null; + this.inputFuture = null; + return; + } + catch (ExecutionException e) { + this.setException(e.getCause()); + this.function = null; + this.inputFuture = null; + return; + } + this.outputFuture = Preconditions.checkNotNull(this.function.apply(sourceResult), "AsyncFunction may not return null."); + final ListenableFuture outputFuture = this.outputFuture; + if (this.isCancelled()) { + outputFuture.cancel(this.wasInterrupted()); + this.outputFuture = null; + return; + } + outputFuture.addListener(new Runnable(){ + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void run() { + try { + ChainingListenableFuture.this.set(Uninterruptibles.getUninterruptibly(outputFuture)); + } + catch (CancellationException e) { + ChainingListenableFuture.this.cancel(false); + return; + } + catch (ExecutionException e) { + ChainingListenableFuture.this.setException(e.getCause()); + } + finally { + ChainingListenableFuture.this.outputFuture = null; + } + } + }, MoreExecutors.directExecutor()); + break block14; + { + catch (UndeclaredThrowableException e) { + this.setException(e.getCause()); + break block14; + } + catch (Throwable t) { + this.setException(t); + break block14; + } + catch (Throwable throwable) { + throw throwable; + } + } + } + finally { + this.function = null; + this.inputFuture = null; + } + } + } + } + + private static class FallbackFuture + extends AbstractFuture { + private volatile ListenableFuture running; + + FallbackFuture(ListenableFuture input, final FutureFallback fallback, Executor executor) { + this.running = input; + Futures.addCallback(this.running, new FutureCallback(){ + + @Override + public void onSuccess(V value) { + FallbackFuture.this.set(value); + } + + @Override + public void onFailure(Throwable t) { + if (FallbackFuture.this.isCancelled()) { + return; + } + try { + FallbackFuture.this.running = fallback.create(t); + if (FallbackFuture.this.isCancelled()) { + FallbackFuture.this.running.cancel(FallbackFuture.this.wasInterrupted()); + return; + } + Futures.addCallback(FallbackFuture.this.running, new FutureCallback(){ + + @Override + public void onSuccess(V value) { + FallbackFuture.this.set(value); + } + + @Override + public void onFailure(Throwable t) { + if (FallbackFuture.this.running.isCancelled()) { + FallbackFuture.this.cancel(false); + } else { + FallbackFuture.this.setException(t); + } + } + }, MoreExecutors.directExecutor()); + } + catch (Throwable e) { + FallbackFuture.this.setException(e); + } + } + }, executor); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (super.cancel(mayInterruptIfRunning)) { + this.running.cancel(mayInterruptIfRunning); + return true; + } + return false; + } + } + + private static class ImmediateFailedCheckedFuture + extends ImmediateFuture + implements CheckedFuture { + private final X thrown; + + ImmediateFailedCheckedFuture(X thrown) { + this.thrown = thrown; + } + + @Override + public V get() throws ExecutionException { + throw new ExecutionException((Throwable)this.thrown); + } + + @Override + public V checkedGet() throws X { + throw this.thrown; + } + + @Override + public V checkedGet(long timeout, TimeUnit unit) throws X { + Preconditions.checkNotNull(unit); + throw this.thrown; + } + } + + private static class ImmediateCancelledFuture + extends ImmediateFuture { + private final CancellationException thrown = new CancellationException("Immediate cancelled future."); + + ImmediateCancelledFuture() { + } + + @Override + public boolean isCancelled() { + return true; + } + + @Override + public V get() { + throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", this.thrown); + } + } + + private static class ImmediateFailedFuture + extends ImmediateFuture { + private final Throwable thrown; + + ImmediateFailedFuture(Throwable thrown) { + this.thrown = thrown; + } + + @Override + public V get() throws ExecutionException { + throw new ExecutionException(this.thrown); + } + } + + private static class ImmediateSuccessfulCheckedFuture + extends ImmediateFuture + implements CheckedFuture { + @Nullable + private final V value; + + ImmediateSuccessfulCheckedFuture(@Nullable V value) { + this.value = value; + } + + @Override + public V get() { + return this.value; + } + + @Override + public V checkedGet() { + return this.value; + } + + @Override + public V checkedGet(long timeout, TimeUnit unit) { + Preconditions.checkNotNull(unit); + return this.value; + } + } + + private static class ImmediateSuccessfulFuture + extends ImmediateFuture { + @Nullable + private final V value; + + ImmediateSuccessfulFuture(@Nullable V value) { + this.value = value; + } + + @Override + public V get() { + return this.value; + } + } + + private static abstract class ImmediateFuture + implements ListenableFuture { + private static final Logger log = Logger.getLogger(ImmediateFuture.class.getName()); + + private ImmediateFuture() { + } + + @Override + public void addListener(Runnable listener, Executor executor) { + Preconditions.checkNotNull(listener, "Runnable was null."); + Preconditions.checkNotNull(executor, "Executor was null."); + try { + executor.execute(listener); + } + catch (RuntimeException e) { + String string = String.valueOf(String.valueOf(listener)); + String string2 = String.valueOf(String.valueOf(executor)); + log.log(Level.SEVERE, new StringBuilder(57 + string.length() + string2.length()).append("RuntimeException while executing runnable ").append(string).append(" with executor ").append(string2).toString(), e); + } + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public abstract V get() throws ExecutionException; + + @Override + public V get(long timeout, TimeUnit unit) throws ExecutionException { + Preconditions.checkNotNull(unit); + return this.get(); + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return true; + } + } +} diff --git a/src/com/google/common/util/concurrent/JdkFutureAdapters.java b/src/com/google/common/util/concurrent/JdkFutureAdapters.java new file mode 100644 index 0000000..eb78071 --- /dev/null +++ b/src/com/google/common/util/concurrent/JdkFutureAdapters.java @@ -0,0 +1,90 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ExecutionList; +import com.google.common.util.concurrent.ForwardingFuture; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.common.util.concurrent.Uninterruptibles; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; + +@Beta +public final class JdkFutureAdapters { + public static ListenableFuture listenInPoolThread(Future future) { + if (future instanceof ListenableFuture) { + return (ListenableFuture)future; + } + return new ListenableFutureAdapter(future); + } + + public static ListenableFuture listenInPoolThread(Future future, Executor executor) { + Preconditions.checkNotNull(executor); + if (future instanceof ListenableFuture) { + return (ListenableFuture)future; + } + return new ListenableFutureAdapter(future, executor); + } + + private JdkFutureAdapters() { + } + + private static class ListenableFutureAdapter + extends ForwardingFuture + implements ListenableFuture { + private static final ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ListenableFutureAdapter-thread-%d").build(); + private static final Executor defaultAdapterExecutor = Executors.newCachedThreadPool(threadFactory); + private final Executor adapterExecutor; + private final ExecutionList executionList = new ExecutionList(); + private final AtomicBoolean hasListeners = new AtomicBoolean(false); + private final Future delegate; + + ListenableFutureAdapter(Future delegate) { + this(delegate, defaultAdapterExecutor); + } + + ListenableFutureAdapter(Future delegate, Executor adapterExecutor) { + this.delegate = Preconditions.checkNotNull(delegate); + this.adapterExecutor = Preconditions.checkNotNull(adapterExecutor); + } + + @Override + protected Future delegate() { + return this.delegate; + } + + @Override + public void addListener(Runnable listener, Executor exec) { + this.executionList.add(listener, exec); + if (this.hasListeners.compareAndSet(false, true)) { + if (this.delegate.isDone()) { + this.executionList.execute(); + return; + } + this.adapterExecutor.execute(new Runnable(){ + + @Override + public void run() { + try { + Uninterruptibles.getUninterruptibly(ListenableFutureAdapter.this.delegate); + } + catch (Error e) { + throw e; + } + catch (Throwable throwable) { + // empty catch block + } + ListenableFutureAdapter.this.executionList.execute(); + } + }); + } + } + } +} diff --git a/src/com/google/common/util/concurrent/ListenableFuture.java b/src/com/google/common/util/concurrent/ListenableFuture.java new file mode 100644 index 0000000..a86edb5 --- /dev/null +++ b/src/com/google/common/util/concurrent/ListenableFuture.java @@ -0,0 +1,12 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import java.util.concurrent.Executor; +import java.util.concurrent.Future; + +public interface ListenableFuture +extends Future { + public void addListener(Runnable var1, Executor var2); +} diff --git a/src/com/google/common/util/concurrent/ListenableFutureTask.java b/src/com/google/common/util/concurrent/ListenableFutureTask.java new file mode 100644 index 0000000..d7a45b6 --- /dev/null +++ b/src/com/google/common/util/concurrent/ListenableFutureTask.java @@ -0,0 +1,43 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.ExecutionList; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.FutureTask; +import javax.annotation.Nullable; + +public class ListenableFutureTask +extends FutureTask +implements ListenableFuture { + private final ExecutionList executionList = new ExecutionList(); + + public static ListenableFutureTask create(Callable callable) { + return new ListenableFutureTask(callable); + } + + public static ListenableFutureTask create(Runnable runnable, @Nullable V result) { + return new ListenableFutureTask(runnable, result); + } + + ListenableFutureTask(Callable callable) { + super(callable); + } + + ListenableFutureTask(Runnable runnable, @Nullable V result) { + super(runnable, result); + } + + @Override + public void addListener(Runnable listener, Executor exec) { + this.executionList.add(listener, exec); + } + + @Override + protected void done() { + this.executionList.execute(); + } +} diff --git a/src/com/google/common/util/concurrent/ListenableScheduledFuture.java b/src/com/google/common/util/concurrent/ListenableScheduledFuture.java new file mode 100644 index 0000000..779fc5a --- /dev/null +++ b/src/com/google/common/util/concurrent/ListenableScheduledFuture.java @@ -0,0 +1,14 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.ScheduledFuture; + +@Beta +public interface ListenableScheduledFuture +extends ScheduledFuture, +ListenableFuture { +} diff --git a/src/com/google/common/util/concurrent/ListenerCallQueue.java b/src/com/google/common/util/concurrent/ListenerCallQueue.java new file mode 100644 index 0000000..1fad437 --- /dev/null +++ b/src/com/google/common/util/concurrent/ListenerCallQueue.java @@ -0,0 +1,121 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Queues; +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + +final class ListenerCallQueue +implements Runnable { + private static final Logger logger = Logger.getLogger(ListenerCallQueue.class.getName()); + private final L listener; + private final Executor executor; + @GuardedBy(value="this") + private final Queue> waitQueue = Queues.newArrayDeque(); + @GuardedBy(value="this") + private boolean isThreadScheduled; + + ListenerCallQueue(L listener, Executor executor) { + this.listener = Preconditions.checkNotNull(listener); + this.executor = Preconditions.checkNotNull(executor); + } + + synchronized void add(Callback callback) { + this.waitQueue.add(callback); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void execute() { + boolean scheduleTaskRunner = false; + ListenerCallQueue listenerCallQueue = this; + synchronized (listenerCallQueue) { + if (!this.isThreadScheduled) { + this.isThreadScheduled = true; + scheduleTaskRunner = true; + } + } + if (scheduleTaskRunner) { + try { + this.executor.execute(this); + } + catch (RuntimeException e) { + Object object = this; + synchronized (object) { + this.isThreadScheduled = false; + } + object = String.valueOf(String.valueOf(this.listener)); + String string = String.valueOf(String.valueOf(this.executor)); + logger.log(Level.SEVERE, new StringBuilder(42 + ((String)object).length() + string.length()).append("Exception while running callbacks for ").append((String)object).append(" on ").append(string).toString(), e); + throw e; + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void run() { + block18: { + boolean stillRunning = true; + block14: while (true) { + while (true) { + Callback nextToRun; + ListenerCallQueue listenerCallQueue = this; + synchronized (listenerCallQueue) { + Preconditions.checkState(this.isThreadScheduled); + nextToRun = this.waitQueue.poll(); + if (nextToRun == null) { + this.isThreadScheduled = false; + stillRunning = false; + break block18; + } + } + try { + nextToRun.call(this.listener); + continue block14; + } + catch (RuntimeException e) { + String string = String.valueOf(String.valueOf(this.listener)); + String string2 = String.valueOf(String.valueOf(((Callback)nextToRun).methodCall)); + logger.log(Level.SEVERE, new StringBuilder(37 + string.length() + string2.length()).append("Exception while executing callback: ").append(string).append(".").append(string2).toString(), e); + continue; + } + break; + } + } + finally { + if (stillRunning) { + ListenerCallQueue listenerCallQueue = this; + synchronized (listenerCallQueue) { + this.isThreadScheduled = false; + } + } + } + } + } + + static abstract class Callback { + private final String methodCall; + + Callback(String methodCall) { + this.methodCall = methodCall; + } + + abstract void call(L var1); + + void enqueueOn(Iterable> queues) { + for (ListenerCallQueue queue : queues) { + queue.add(this); + } + } + } +} diff --git a/src/com/google/common/util/concurrent/ListeningExecutorService.java b/src/com/google/common/util/concurrent/ListeningExecutorService.java new file mode 100644 index 0000000..a1977a4 --- /dev/null +++ b/src/com/google/common/util/concurrent/ListeningExecutorService.java @@ -0,0 +1,27 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +public interface ListeningExecutorService +extends ExecutorService { + public ListenableFuture submit(Callable var1); + + public ListenableFuture submit(Runnable var1); + + public ListenableFuture submit(Runnable var1, T var2); + + @Override + public List> invokeAll(Collection> var1) throws InterruptedException; + + @Override + public List> invokeAll(Collection> var1, long var2, TimeUnit var4) throws InterruptedException; +} diff --git a/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java b/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java new file mode 100644 index 0000000..5fda77c --- /dev/null +++ b/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java @@ -0,0 +1,24 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableScheduledFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Beta +public interface ListeningScheduledExecutorService +extends ScheduledExecutorService, +ListeningExecutorService { + public ListenableScheduledFuture schedule(Runnable var1, long var2, TimeUnit var4); + + public ListenableScheduledFuture schedule(Callable var1, long var2, TimeUnit var4); + + public ListenableScheduledFuture scheduleAtFixedRate(Runnable var1, long var2, long var4, TimeUnit var6); + + public ListenableScheduledFuture scheduleWithFixedDelay(Runnable var1, long var2, long var4, TimeUnit var6); +} diff --git a/src/com/google/common/util/concurrent/Monitor.java b/src/com/google/common/util/concurrent/Monitor.java new file mode 100644 index 0000000..9744c37 --- /dev/null +++ b/src/com/google/common/util/concurrent/Monitor.java @@ -0,0 +1,599 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import javax.annotation.concurrent.GuardedBy; + +@Beta +public final class Monitor { + private final boolean fair; + private final ReentrantLock lock; + @GuardedBy(value="lock") + private Guard activeGuards = null; + + public Monitor() { + this(false); + } + + public Monitor(boolean fair) { + this.fair = fair; + this.lock = new ReentrantLock(fair); + } + + public void enter() { + this.lock.lock(); + } + + public void enterInterruptibly() throws InterruptedException { + this.lock.lockInterruptibly(); + } + + public boolean enter(long time, TimeUnit unit) { + long timeoutNanos = unit.toNanos(time); + ReentrantLock lock = this.lock; + if (!this.fair && lock.tryLock()) { + return true; + } + long deadline = System.nanoTime() + timeoutNanos; + boolean interrupted = Thread.interrupted(); + while (true) { + try { + boolean bl = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS); + return bl; + } + catch (InterruptedException interrupt) { + interrupted = true; + timeoutNanos = deadline - System.nanoTime(); + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException { + return this.lock.tryLock(time, unit); + } + + public boolean tryEnter() { + return this.lock.tryLock(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void enterWhen(Guard guard) throws InterruptedException { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean signalBeforeWaiting = lock.isHeldByCurrentThread(); + lock.lockInterruptibly(); + boolean satisfied = false; + try { + if (!guard.isSatisfied()) { + this.await(guard, signalBeforeWaiting); + } + satisfied = true; + } + finally { + if (!satisfied) { + this.leave(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void enterWhenUninterruptibly(Guard guard) { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean signalBeforeWaiting = lock.isHeldByCurrentThread(); + lock.lock(); + boolean satisfied = false; + try { + if (!guard.isSatisfied()) { + this.awaitUninterruptibly(guard, signalBeforeWaiting); + } + satisfied = true; + } + finally { + if (!satisfied) { + this.leave(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException { + long timeoutNanos = unit.toNanos(time); + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean reentrant = lock.isHeldByCurrentThread(); + if (this.fair || !lock.tryLock()) { + long deadline = System.nanoTime() + timeoutNanos; + if (!lock.tryLock(time, unit)) { + return false; + } + timeoutNanos = deadline - System.nanoTime(); + } + boolean satisfied = false; + boolean threw = true; + try { + satisfied = guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, reentrant); + threw = false; + boolean bl = satisfied; + return bl; + } + finally { + if (!satisfied) { + try { + if (threw && !reentrant) { + this.signalNextWaiter(); + } + } + finally { + lock.unlock(); + } + } + } + } + + /* + * Loose catch block + */ + public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) { + long timeoutNanos = unit.toNanos(time); + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + long deadline = System.nanoTime() + timeoutNanos; + boolean signalBeforeWaiting = lock.isHeldByCurrentThread(); + boolean interrupted = Thread.interrupted(); + try { + if (this.fair || !lock.tryLock()) { + boolean locked = false; + do { + try { + locked = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS); + if (!locked) { + boolean bl = false; + return bl; + } + } + catch (InterruptedException interrupt) { + interrupted = true; + } + timeoutNanos = deadline - System.nanoTime(); + } while (!locked); + } + boolean satisfied = false; + while (true) { + try { + satisfied = guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, signalBeforeWaiting); + boolean interrupt = satisfied; + return interrupt; + } + catch (InterruptedException interrupt) { + interrupted = true; + signalBeforeWaiting = false; + timeoutNanos = deadline - System.nanoTime(); + continue; + } + break; + } + finally { + if (!satisfied) { + lock.unlock(); + } + } + { + catch (Throwable throwable) { + throw throwable; + } + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean enterIf(Guard guard) { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + lock.lock(); + boolean satisfied = false; + try { + boolean bl = satisfied = guard.isSatisfied(); + return bl; + } + finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean enterIfInterruptibly(Guard guard) throws InterruptedException { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + boolean satisfied = false; + try { + boolean bl = satisfied = guard.isSatisfied(); + return bl; + } + finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean enterIf(Guard guard, long time, TimeUnit unit) { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + if (!this.enter(time, unit)) { + return false; + } + boolean satisfied = false; + try { + boolean bl = satisfied = guard.isSatisfied(); + return bl; + } + finally { + if (!satisfied) { + this.lock.unlock(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit) throws InterruptedException { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + if (!lock.tryLock(time, unit)) { + return false; + } + boolean satisfied = false; + try { + boolean bl = satisfied = guard.isSatisfied(); + return bl; + } + finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean tryEnterIf(Guard guard) { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + if (!lock.tryLock()) { + return false; + } + boolean satisfied = false; + try { + boolean bl = satisfied = guard.isSatisfied(); + return bl; + } + finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + public void waitFor(Guard guard) throws InterruptedException { + if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (!guard.isSatisfied()) { + this.await(guard, true); + } + } + + public void waitForUninterruptibly(Guard guard) { + if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (!guard.isSatisfied()) { + this.awaitUninterruptibly(guard, true); + } + } + + public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException { + long timeoutNanos = unit.toNanos(time); + if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + return guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, true); + } + + public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) { + long timeoutNanos = unit.toNanos(time); + if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (guard.isSatisfied()) { + return true; + } + boolean signalBeforeWaiting = true; + long deadline = System.nanoTime() + timeoutNanos; + boolean interrupted = Thread.interrupted(); + while (true) { + try { + boolean bl = this.awaitNanos(guard, timeoutNanos, signalBeforeWaiting); + return bl; + } + catch (InterruptedException interrupt) { + interrupted = true; + if (guard.isSatisfied()) { + boolean bl = true; + return bl; + } + signalBeforeWaiting = false; + timeoutNanos = deadline - System.nanoTime(); + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public void leave() { + ReentrantLock lock = this.lock; + try { + if (lock.getHoldCount() == 1) { + this.signalNextWaiter(); + } + } + finally { + lock.unlock(); + } + } + + public boolean isFair() { + return this.fair; + } + + public boolean isOccupied() { + return this.lock.isLocked(); + } + + public boolean isOccupiedByCurrentThread() { + return this.lock.isHeldByCurrentThread(); + } + + public int getOccupiedDepth() { + return this.lock.getHoldCount(); + } + + public int getQueueLength() { + return this.lock.getQueueLength(); + } + + public boolean hasQueuedThreads() { + return this.lock.hasQueuedThreads(); + } + + public boolean hasQueuedThread(Thread thread) { + return this.lock.hasQueuedThread(thread); + } + + public boolean hasWaiters(Guard guard) { + return this.getWaitQueueLength(guard) > 0; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public int getWaitQueueLength(Guard guard) { + if (guard.monitor != this) { + throw new IllegalMonitorStateException(); + } + this.lock.lock(); + try { + int n = guard.waiterCount; + return n; + } + finally { + this.lock.unlock(); + } + } + + @GuardedBy(value="lock") + private void signalNextWaiter() { + Guard guard = this.activeGuards; + while (guard != null) { + if (this.isSatisfied(guard)) { + guard.condition.signal(); + break; + } + guard = guard.next; + } + } + + @GuardedBy(value="lock") + private boolean isSatisfied(Guard guard) { + try { + return guard.isSatisfied(); + } + catch (Throwable throwable) { + this.signalAllWaiters(); + throw Throwables.propagate(throwable); + } + } + + @GuardedBy(value="lock") + private void signalAllWaiters() { + Guard guard = this.activeGuards; + while (guard != null) { + guard.condition.signalAll(); + guard = guard.next; + } + } + + @GuardedBy(value="lock") + private void beginWaitingFor(Guard guard) { + int waiters; + if ((waiters = guard.waiterCount++) == 0) { + guard.next = this.activeGuards; + this.activeGuards = guard; + } + } + + @GuardedBy(value="lock") + private void endWaitingFor(Guard guard) { + int waiters; + if ((waiters = --guard.waiterCount) == 0) { + Guard p = this.activeGuards; + Guard pred = null; + while (true) { + if (p == guard) { + if (pred == null) { + this.activeGuards = p.next; + } else { + pred.next = p.next; + } + p.next = null; + break; + } + pred = p; + p = p.next; + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @GuardedBy(value="lock") + private void await(Guard guard, boolean signalBeforeWaiting) throws InterruptedException { + if (signalBeforeWaiting) { + this.signalNextWaiter(); + } + this.beginWaitingFor(guard); + try { + do { + guard.condition.await(); + } while (!guard.isSatisfied()); + } + finally { + this.endWaitingFor(guard); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @GuardedBy(value="lock") + private void awaitUninterruptibly(Guard guard, boolean signalBeforeWaiting) { + if (signalBeforeWaiting) { + this.signalNextWaiter(); + } + this.beginWaitingFor(guard); + try { + do { + guard.condition.awaitUninterruptibly(); + } while (!guard.isSatisfied()); + } + finally { + this.endWaitingFor(guard); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @GuardedBy(value="lock") + private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting) throws InterruptedException { + if (signalBeforeWaiting) { + this.signalNextWaiter(); + } + this.beginWaitingFor(guard); + try { + do { + if (nanos < 0L) { + boolean bl = false; + return bl; + } + nanos = guard.condition.awaitNanos(nanos); + } while (!guard.isSatisfied()); + boolean bl = true; + return bl; + } + finally { + this.endWaitingFor(guard); + } + } + + @Beta + public static abstract class Guard { + final Monitor monitor; + final Condition condition; + @GuardedBy(value="monitor.lock") + int waiterCount = 0; + @GuardedBy(value="monitor.lock") + Guard next; + + protected Guard(Monitor monitor) { + this.monitor = Preconditions.checkNotNull(monitor, "monitor"); + this.condition = monitor.lock.newCondition(); + } + + public abstract boolean isSatisfied(); + } +} diff --git a/src/com/google/common/util/concurrent/MoreExecutors.java b/src/com/google/common/util/concurrent/MoreExecutors.java new file mode 100644 index 0000000..149851e --- /dev/null +++ b/src/com/google/common/util/concurrent/MoreExecutors.java @@ -0,0 +1,632 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Queues; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.AbstractListeningExecutorService; +import com.google.common.util.concurrent.Callables; +import com.google.common.util.concurrent.ForwardingListenableFuture; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import com.google.common.util.concurrent.ListenableScheduledFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.ListeningScheduledExecutorService; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.common.util.concurrent.WrappingExecutorService; +import com.google.common.util.concurrent.WrappingScheduledExecutorService; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.Delayed; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public final class MoreExecutors { + private MoreExecutors() { + } + + @Beta + public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { + return new Application().getExitingExecutorService(executor, terminationTimeout, timeUnit); + } + + @Beta + public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { + return new Application().getExitingScheduledExecutorService(executor, terminationTimeout, timeUnit); + } + + @Beta + public static void addDelayedShutdownHook(ExecutorService service, long terminationTimeout, TimeUnit timeUnit) { + new Application().addDelayedShutdownHook(service, terminationTimeout, timeUnit); + } + + @Beta + public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) { + return new Application().getExitingExecutorService(executor); + } + + @Beta + public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) { + return new Application().getExitingScheduledExecutorService(executor); + } + + private static void useDaemonThreadFactory(ThreadPoolExecutor executor) { + executor.setThreadFactory(new ThreadFactoryBuilder().setDaemon(true).setThreadFactory(executor.getThreadFactory()).build()); + } + + @Deprecated + public static ListeningExecutorService sameThreadExecutor() { + return new DirectExecutorService(); + } + + public static ListeningExecutorService newDirectExecutorService() { + return new DirectExecutorService(); + } + + public static Executor directExecutor() { + return DirectExecutor.INSTANCE; + } + + public static ListeningExecutorService listeningDecorator(ExecutorService delegate) { + return delegate instanceof ListeningExecutorService ? (ListeningExecutorService)delegate : (delegate instanceof ScheduledExecutorService ? new ScheduledListeningDecorator((ScheduledExecutorService)delegate) : new ListeningDecorator(delegate)); + } + + public static ListeningScheduledExecutorService listeningDecorator(ScheduledExecutorService delegate) { + return delegate instanceof ListeningScheduledExecutorService ? (ListeningScheduledExecutorService)delegate : new ScheduledListeningDecorator(delegate); + } + + static T invokeAnyImpl(ListeningExecutorService executorService, Collection> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException { + ExecutionException ee; + ArrayList> futures; + block15: { + Preconditions.checkNotNull(executorService); + int ntasks = tasks.size(); + Preconditions.checkArgument(ntasks > 0); + futures = Lists.newArrayListWithCapacity(ntasks); + LinkedBlockingQueue> futureQueue = Queues.newLinkedBlockingQueue(); + ee = null; + long lastTime = timed ? System.nanoTime() : 0L; + Iterator> it = tasks.iterator(); + futures.add(MoreExecutors.submitAndAddQueueListener(executorService, it.next(), futureQueue)); + --ntasks; + int active = 1; + while (true) { + Object now22; + Future f; + if ((f = (Future)futureQueue.poll()) == null) { + if (ntasks > 0) { + --ntasks; + futures.add(MoreExecutors.submitAndAddQueueListener(executorService, it.next(), futureQueue)); + ++active; + } else { + if (active == 0) break; + if (timed) { + f = (Future)futureQueue.poll(nanos, TimeUnit.NANOSECONDS); + if (f == null) { + throw new TimeoutException(); + } + long now22 = System.nanoTime(); + nanos -= now22 - lastTime; + lastTime = now22; + } else { + f = (Future)futureQueue.take(); + } + } + } + if (f == null) continue; + --active; + try { + now22 = f.get(); + } + catch (ExecutionException eex) { + ee = eex; + continue; + } + catch (RuntimeException rex) { + ee = new ExecutionException(rex); + continue; + } + return (T)now22; + break; + } + if (ee != null) break block15; + ee = new ExecutionException(null); + } + throw ee; + finally { + for (Future future : futures) { + future.cancel(true); + } + } + } + + private static ListenableFuture submitAndAddQueueListener(ListeningExecutorService executorService, Callable task, final BlockingQueue> queue) { + final ListenableFuture future = executorService.submit(task); + future.addListener(new Runnable(){ + + @Override + public void run() { + queue.add(future); + } + }, MoreExecutors.directExecutor()); + return future; + } + + @Beta + public static ThreadFactory platformThreadFactory() { + if (!MoreExecutors.isAppEngine()) { + return Executors.defaultThreadFactory(); + } + try { + return (ThreadFactory)Class.forName("com.google.appengine.api.ThreadManager").getMethod("currentRequestThreadFactory", new Class[0]).invoke(null, new Object[0]); + } + catch (IllegalAccessException e) { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } + catch (NoSuchMethodException e) { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } + catch (InvocationTargetException e) { + throw Throwables.propagate(e.getCause()); + } + } + + private static boolean isAppEngine() { + if (System.getProperty("com.google.appengine.runtime.environment") == null) { + return false; + } + try { + return Class.forName("com.google.apphosting.api.ApiProxy").getMethod("getCurrentEnvironment", new Class[0]).invoke(null, new Object[0]) != null; + } + catch (ClassNotFoundException e) { + return false; + } + catch (InvocationTargetException e) { + return false; + } + catch (IllegalAccessException e) { + return false; + } + catch (NoSuchMethodException e) { + return false; + } + } + + static Thread newThread(String name, Runnable runnable) { + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(runnable); + Thread result = MoreExecutors.platformThreadFactory().newThread(runnable); + try { + result.setName(name); + } + catch (SecurityException securityException) { + // empty catch block + } + return result; + } + + static Executor renamingDecorator(final Executor executor, final Supplier nameSupplier) { + Preconditions.checkNotNull(executor); + Preconditions.checkNotNull(nameSupplier); + if (MoreExecutors.isAppEngine()) { + return executor; + } + return new Executor(){ + + @Override + public void execute(Runnable command) { + executor.execute(Callables.threadRenaming(command, (Supplier)nameSupplier)); + } + }; + } + + static ExecutorService renamingDecorator(ExecutorService service, final Supplier nameSupplier) { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(nameSupplier); + if (MoreExecutors.isAppEngine()) { + return service; + } + return new WrappingExecutorService(service){ + + @Override + protected Callable wrapTask(Callable callable) { + return Callables.threadRenaming(callable, (Supplier)nameSupplier); + } + + @Override + protected Runnable wrapTask(Runnable command) { + return Callables.threadRenaming(command, (Supplier)nameSupplier); + } + }; + } + + static ScheduledExecutorService renamingDecorator(ScheduledExecutorService service, final Supplier nameSupplier) { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(nameSupplier); + if (MoreExecutors.isAppEngine()) { + return service; + } + return new WrappingScheduledExecutorService(service){ + + @Override + protected Callable wrapTask(Callable callable) { + return Callables.threadRenaming(callable, (Supplier)nameSupplier); + } + + @Override + protected Runnable wrapTask(Runnable command) { + return Callables.threadRenaming(command, (Supplier)nameSupplier); + } + }; + } + + @Beta + public static boolean shutdownAndAwaitTermination(ExecutorService service, long timeout, TimeUnit unit) { + Preconditions.checkNotNull(unit); + service.shutdown(); + try { + long halfTimeoutNanos = TimeUnit.NANOSECONDS.convert(timeout, unit) / 2L; + if (!service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS)) { + service.shutdownNow(); + service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS); + } + } + catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + service.shutdownNow(); + } + return service.isTerminated(); + } + + private static class ScheduledListeningDecorator + extends ListeningDecorator + implements ListeningScheduledExecutorService { + final ScheduledExecutorService delegate; + + ScheduledListeningDecorator(ScheduledExecutorService delegate) { + super(delegate); + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public ListenableScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { + ListenableFutureTask task = ListenableFutureTask.create(command, null); + ScheduledFuture scheduled = this.delegate.schedule(task, delay, unit); + return new ListenableScheduledTask(task, scheduled); + } + + @Override + public ListenableScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { + ListenableFutureTask task = ListenableFutureTask.create(callable); + ScheduledFuture scheduled = this.delegate.schedule(task, delay, unit); + return new ListenableScheduledTask(task, scheduled); + } + + @Override + public ListenableScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { + NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command); + ScheduledFuture scheduled = this.delegate.scheduleAtFixedRate(task, initialDelay, period, unit); + return new ListenableScheduledTask(task, scheduled); + } + + @Override + public ListenableScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { + NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command); + ScheduledFuture scheduled = this.delegate.scheduleWithFixedDelay(task, initialDelay, delay, unit); + return new ListenableScheduledTask(task, scheduled); + } + + private static final class NeverSuccessfulListenableFutureTask + extends AbstractFuture + implements Runnable { + private final Runnable delegate; + + public NeverSuccessfulListenableFutureTask(Runnable delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public void run() { + try { + this.delegate.run(); + } + catch (Throwable t) { + this.setException(t); + throw Throwables.propagate(t); + } + } + } + + private static final class ListenableScheduledTask + extends ForwardingListenableFuture.SimpleForwardingListenableFuture + implements ListenableScheduledFuture { + private final ScheduledFuture scheduledDelegate; + + public ListenableScheduledTask(ListenableFuture listenableDelegate, ScheduledFuture scheduledDelegate) { + super(listenableDelegate); + this.scheduledDelegate = scheduledDelegate; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + boolean cancelled = super.cancel(mayInterruptIfRunning); + if (cancelled) { + this.scheduledDelegate.cancel(mayInterruptIfRunning); + } + return cancelled; + } + + @Override + public long getDelay(TimeUnit unit) { + return this.scheduledDelegate.getDelay(unit); + } + + @Override + public int compareTo(Delayed other) { + return this.scheduledDelegate.compareTo(other); + } + } + } + + private static class ListeningDecorator + extends AbstractListeningExecutorService { + private final ExecutorService delegate; + + ListeningDecorator(ExecutorService delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate.awaitTermination(timeout, unit); + } + + @Override + public boolean isShutdown() { + return this.delegate.isShutdown(); + } + + @Override + public boolean isTerminated() { + return this.delegate.isTerminated(); + } + + @Override + public void shutdown() { + this.delegate.shutdown(); + } + + @Override + public List shutdownNow() { + return this.delegate.shutdownNow(); + } + + @Override + public void execute(Runnable command) { + this.delegate.execute(command); + } + } + + private static enum DirectExecutor implements Executor + { + INSTANCE; + + + @Override + public void execute(Runnable command) { + command.run(); + } + } + + private static class DirectExecutorService + extends AbstractListeningExecutorService { + private final Lock lock = new ReentrantLock(); + private final Condition termination = this.lock.newCondition(); + private int runningTasks = 0; + private boolean shutdown = false; + + private DirectExecutorService() { + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void execute(Runnable command) { + this.startTask(); + try { + command.run(); + } + finally { + this.endTask(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean isShutdown() { + this.lock.lock(); + try { + boolean bl = this.shutdown; + return bl; + } + finally { + this.lock.unlock(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void shutdown() { + this.lock.lock(); + try { + this.shutdown = true; + } + finally { + this.lock.unlock(); + } + } + + @Override + public List shutdownNow() { + this.shutdown(); + return Collections.emptyList(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public boolean isTerminated() { + this.lock.lock(); + try { + boolean bl = this.shutdown && this.runningTasks == 0; + return bl; + } + finally { + this.lock.unlock(); + } + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + long nanos = unit.toNanos(timeout); + this.lock.lock(); + try { + while (true) { + if (this.isTerminated()) { + boolean bl = true; + return bl; + } + if (nanos <= 0L) { + boolean bl = false; + return bl; + } + nanos = this.termination.awaitNanos(nanos); + } + } + finally { + this.lock.unlock(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private void startTask() { + this.lock.lock(); + try { + if (this.isShutdown()) { + throw new RejectedExecutionException("Executor already shutdown"); + } + ++this.runningTasks; + } + finally { + this.lock.unlock(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private void endTask() { + this.lock.lock(); + try { + --this.runningTasks; + if (this.isTerminated()) { + this.termination.signalAll(); + } + } + finally { + this.lock.unlock(); + } + } + } + + @VisibleForTesting + static class Application { + Application() { + } + + final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { + MoreExecutors.useDaemonThreadFactory(executor); + ExecutorService service = Executors.unconfigurableExecutorService(executor); + this.addDelayedShutdownHook(service, terminationTimeout, timeUnit); + return service; + } + + final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { + MoreExecutors.useDaemonThreadFactory(executor); + ScheduledExecutorService service = Executors.unconfigurableScheduledExecutorService(executor); + this.addDelayedShutdownHook(service, terminationTimeout, timeUnit); + return service; + } + + final void addDelayedShutdownHook(final ExecutorService service, final long terminationTimeout, final TimeUnit timeUnit) { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(timeUnit); + String string = String.valueOf(String.valueOf(service)); + this.addShutdownHook(MoreExecutors.newThread(new StringBuilder(24 + string.length()).append("DelayedShutdownHook-for-").append(string).toString(), new Runnable(){ + + @Override + public void run() { + try { + service.shutdown(); + service.awaitTermination(terminationTimeout, timeUnit); + } + catch (InterruptedException interruptedException) { + // empty catch block + } + } + })); + } + + final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) { + return this.getExitingExecutorService(executor, 120L, TimeUnit.SECONDS); + } + + final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) { + return this.getExitingScheduledExecutorService(executor, 120L, TimeUnit.SECONDS); + } + + @VisibleForTesting + void addShutdownHook(Thread hook) { + Runtime.getRuntime().addShutdownHook(hook); + } + } +} diff --git a/src/com/google/common/util/concurrent/RateLimiter.java b/src/com/google/common/util/concurrent/RateLimiter.java new file mode 100644 index 0000000..2844770 --- /dev/null +++ b/src/com/google/common/util/concurrent/RateLimiter.java @@ -0,0 +1,191 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; +import com.google.common.util.concurrent.SmoothRateLimiter; +import com.google.common.util.concurrent.Uninterruptibles; +import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.ThreadSafe; + +@ThreadSafe +@Beta +public abstract class RateLimiter { + private final SleepingStopwatch stopwatch; + private volatile Object mutexDoNotUseDirectly; + + public static RateLimiter create(double permitsPerSecond) { + return RateLimiter.create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond); + } + + @VisibleForTesting + static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond) { + SmoothRateLimiter.SmoothBursty rateLimiter = new SmoothRateLimiter.SmoothBursty(stopwatch, 1.0); + rateLimiter.setRate(permitsPerSecond); + return rateLimiter; + } + + public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) { + Preconditions.checkArgument(warmupPeriod >= 0L, "warmupPeriod must not be negative: %s", warmupPeriod); + return RateLimiter.create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit); + } + + @VisibleForTesting + static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit) { + SmoothRateLimiter.SmoothWarmingUp rateLimiter = new SmoothRateLimiter.SmoothWarmingUp(stopwatch, warmupPeriod, unit); + rateLimiter.setRate(permitsPerSecond); + return rateLimiter; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + private Object mutex() { + Object mutex = this.mutexDoNotUseDirectly; + if (mutex == null) { + RateLimiter rateLimiter = this; + synchronized (rateLimiter) { + mutex = this.mutexDoNotUseDirectly; + if (mutex == null) { + this.mutexDoNotUseDirectly = mutex = new Object(); + } + } + } + return mutex; + } + + RateLimiter(SleepingStopwatch stopwatch) { + this.stopwatch = Preconditions.checkNotNull(stopwatch); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public final void setRate(double permitsPerSecond) { + Preconditions.checkArgument(permitsPerSecond > 0.0 && !Double.isNaN(permitsPerSecond), "rate must be positive"); + Object object = this.mutex(); + synchronized (object) { + this.doSetRate(permitsPerSecond, this.stopwatch.readMicros()); + } + } + + abstract void doSetRate(double var1, long var3); + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public final double getRate() { + Object object = this.mutex(); + synchronized (object) { + return this.doGetRate(); + } + } + + abstract double doGetRate(); + + public double acquire() { + return this.acquire(1); + } + + public double acquire(int permits) { + long microsToWait = this.reserve(permits); + this.stopwatch.sleepMicrosUninterruptibly(microsToWait); + return 1.0 * (double)microsToWait / (double)TimeUnit.SECONDS.toMicros(1L); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + final long reserve(int permits) { + RateLimiter.checkPermits(permits); + Object object = this.mutex(); + synchronized (object) { + return this.reserveAndGetWaitLength(permits, this.stopwatch.readMicros()); + } + } + + public boolean tryAcquire(long timeout, TimeUnit unit) { + return this.tryAcquire(1, timeout, unit); + } + + public boolean tryAcquire(int permits) { + return this.tryAcquire(permits, 0L, TimeUnit.MICROSECONDS); + } + + public boolean tryAcquire() { + return this.tryAcquire(1, 0L, TimeUnit.MICROSECONDS); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + public boolean tryAcquire(int permits, long timeout, TimeUnit unit) { + long microsToWait; + long timeoutMicros = Math.max(unit.toMicros(timeout), 0L); + RateLimiter.checkPermits(permits); + Object object = this.mutex(); + synchronized (object) { + long nowMicros = this.stopwatch.readMicros(); + if (!this.canAcquire(nowMicros, timeoutMicros)) { + return false; + } + microsToWait = this.reserveAndGetWaitLength(permits, nowMicros); + } + this.stopwatch.sleepMicrosUninterruptibly(microsToWait); + return true; + } + + private boolean canAcquire(long nowMicros, long timeoutMicros) { + return this.queryEarliestAvailable(nowMicros) - timeoutMicros <= nowMicros; + } + + final long reserveAndGetWaitLength(int permits, long nowMicros) { + long momentAvailable = this.reserveEarliestAvailable(permits, nowMicros); + return Math.max(momentAvailable - nowMicros, 0L); + } + + abstract long queryEarliestAvailable(long var1); + + abstract long reserveEarliestAvailable(int var1, long var2); + + public String toString() { + return String.format("RateLimiter[stableRate=%3.1fqps]", this.getRate()); + } + + private static int checkPermits(int permits) { + Preconditions.checkArgument(permits > 0, "Requested permits (%s) must be positive", permits); + return permits; + } + + @VisibleForTesting + static abstract class SleepingStopwatch { + SleepingStopwatch() { + } + + abstract long readMicros(); + + abstract void sleepMicrosUninterruptibly(long var1); + + static final SleepingStopwatch createFromSystemTimer() { + return new SleepingStopwatch(){ + final Stopwatch stopwatch = Stopwatch.createStarted(); + + @Override + long readMicros() { + return this.stopwatch.elapsed(TimeUnit.MICROSECONDS); + } + + @Override + void sleepMicrosUninterruptibly(long micros) { + if (micros > 0L) { + Uninterruptibles.sleepUninterruptibly(micros, TimeUnit.MICROSECONDS); + } + } + }; + } + } +} diff --git a/src/com/google/common/util/concurrent/Runnables.java b/src/com/google/common/util/concurrent/Runnables.java new file mode 100644 index 0000000..cb18196 --- /dev/null +++ b/src/com/google/common/util/concurrent/Runnables.java @@ -0,0 +1,25 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public final class Runnables { + private static final Runnable EMPTY_RUNNABLE = new Runnable(){ + + @Override + public void run() { + } + }; + + public static Runnable doNothing() { + return EMPTY_RUNNABLE; + } + + private Runnables() { + } +} diff --git a/src/com/google/common/util/concurrent/SerializingExecutor.java b/src/com/google/common/util/concurrent/SerializingExecutor.java new file mode 100644 index 0000000..62411ef --- /dev/null +++ b/src/com/google/common/util/concurrent/SerializingExecutor.java @@ -0,0 +1,116 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + +final class SerializingExecutor +implements Executor { + private static final Logger log = Logger.getLogger(SerializingExecutor.class.getName()); + private final Executor executor; + @GuardedBy(value="internalLock") + private final Queue waitQueue = new ArrayDeque(); + @GuardedBy(value="internalLock") + private boolean isThreadScheduled = false; + private final TaskRunner taskRunner = new TaskRunner(); + private final Object internalLock = new Object(){ + + public String toString() { + String string = String.valueOf(super.toString()); + return string.length() != 0 ? "SerializingExecutor lock: ".concat(string) : new String("SerializingExecutor lock: "); + } + }; + + public SerializingExecutor(Executor executor) { + Preconditions.checkNotNull(executor, "'executor' must not be null."); + this.executor = executor; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void execute(Runnable r) { + Preconditions.checkNotNull(r, "'r' must not be null."); + boolean scheduleTaskRunner = false; + Object object = this.internalLock; + synchronized (object) { + this.waitQueue.add(r); + if (!this.isThreadScheduled) { + this.isThreadScheduled = true; + scheduleTaskRunner = true; + } + } + if (scheduleTaskRunner) { + boolean threw = true; + try { + this.executor.execute(this.taskRunner); + threw = false; + } + finally { + if (threw) { + Object object2 = this.internalLock; + synchronized (object2) { + this.isThreadScheduled = false; + } + } + } + } + } + + private class TaskRunner + implements Runnable { + private TaskRunner() { + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void run() { + block18: { + boolean stillRunning = true; + block14: while (true) { + while (true) { + Runnable nextToRun; + Preconditions.checkState(SerializingExecutor.this.isThreadScheduled); + Object object = SerializingExecutor.this.internalLock; + synchronized (object) { + nextToRun = (Runnable)SerializingExecutor.this.waitQueue.poll(); + if (nextToRun == null) { + SerializingExecutor.this.isThreadScheduled = false; + stillRunning = false; + break block18; + } + } + try { + nextToRun.run(); + continue block14; + } + catch (RuntimeException e) { + String string = String.valueOf(String.valueOf(nextToRun)); + log.log(Level.SEVERE, new StringBuilder(35 + string.length()).append("Exception while executing runnable ").append(string).toString(), e); + continue; + } + break; + } + } + finally { + if (stillRunning) { + Object object = SerializingExecutor.this.internalLock; + synchronized (object) { + SerializingExecutor.this.isThreadScheduled = false; + } + } + } + } + } + } +} diff --git a/src/com/google/common/util/concurrent/Service.java b/src/com/google/common/util/concurrent/Service.java new file mode 100644 index 0000000..47a0c6f --- /dev/null +++ b/src/com/google/common/util/concurrent/Service.java @@ -0,0 +1,104 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public interface Service { + public Service startAsync(); + + public boolean isRunning(); + + public State state(); + + public Service stopAsync(); + + public void awaitRunning(); + + public void awaitRunning(long var1, TimeUnit var3) throws TimeoutException; + + public void awaitTerminated(); + + public void awaitTerminated(long var1, TimeUnit var3) throws TimeoutException; + + public Throwable failureCause(); + + public void addListener(Listener var1, Executor var2); + + @Beta + public static abstract class Listener { + public void starting() { + } + + public void running() { + } + + public void stopping(State from) { + } + + public void terminated(State from) { + } + + public void failed(State from, Throwable failure) { + } + } + + @Beta + public static enum State { + NEW{ + + @Override + boolean isTerminal() { + return false; + } + } + , + STARTING{ + + @Override + boolean isTerminal() { + return false; + } + } + , + RUNNING{ + + @Override + boolean isTerminal() { + return false; + } + } + , + STOPPING{ + + @Override + boolean isTerminal() { + return false; + } + } + , + TERMINATED{ + + @Override + boolean isTerminal() { + return true; + } + } + , + FAILED{ + + @Override + boolean isTerminal() { + return true; + } + }; + + + abstract boolean isTerminal(); + } +} diff --git a/src/com/google/common/util/concurrent/ServiceManager.java b/src/com/google/common/util/concurrent/ServiceManager.java new file mode 100644 index 0000000..6fd7f39 --- /dev/null +++ b/src/com/google/common/util/concurrent/ServiceManager.java @@ -0,0 +1,528 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.base.Stopwatch; +import com.google.common.base.Supplier; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.AbstractService; +import com.google.common.util.concurrent.ListenerCallQueue; +import com.google.common.util.concurrent.Monitor; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + +@Beta +public final class ServiceManager { + private static final Logger logger = Logger.getLogger(ServiceManager.class.getName()); + private static final ListenerCallQueue.Callback HEALTHY_CALLBACK = new ListenerCallQueue.Callback("healthy()"){ + + @Override + void call(Listener listener) { + listener.healthy(); + } + }; + private static final ListenerCallQueue.Callback STOPPED_CALLBACK = new ListenerCallQueue.Callback("stopped()"){ + + @Override + void call(Listener listener) { + listener.stopped(); + } + }; + private final ServiceManagerState state; + private final ImmutableList services; + + public ServiceManager(Iterable services) { + ImmutableList copy = ImmutableList.copyOf(services); + if (copy.isEmpty()) { + logger.log(Level.WARNING, "ServiceManager configured with no services. Is your application configured properly?", new EmptyServiceManagerWarning()); + copy = ImmutableList.of(new NoOpService()); + } + this.state = new ServiceManagerState(copy); + this.services = copy; + WeakReference stateReference = new WeakReference(this.state); + for (Service service : copy) { + service.addListener(new ServiceListener(service, stateReference), MoreExecutors.directExecutor()); + Preconditions.checkArgument(service.state() == Service.State.NEW, "Can only manage NEW services, %s", service); + } + this.state.markReady(); + } + + public void addListener(Listener listener, Executor executor) { + this.state.addListener(listener, executor); + } + + public void addListener(Listener listener) { + this.state.addListener(listener, MoreExecutors.directExecutor()); + } + + public ServiceManager startAsync() { + for (Service service : this.services) { + Service.State state = service.state(); + Preconditions.checkState(state == Service.State.NEW, "Service %s is %s, cannot start it.", new Object[]{service, state}); + } + for (Service service : this.services) { + try { + this.state.tryStartTiming(service); + service.startAsync(); + } + catch (IllegalStateException e) { + String string = String.valueOf(String.valueOf(service)); + logger.log(Level.WARNING, new StringBuilder(24 + string.length()).append("Unable to start Service ").append(string).toString(), e); + } + } + return this; + } + + public void awaitHealthy() { + this.state.awaitHealthy(); + } + + public void awaitHealthy(long timeout, TimeUnit unit) throws TimeoutException { + this.state.awaitHealthy(timeout, unit); + } + + public ServiceManager stopAsync() { + for (Service service : this.services) { + service.stopAsync(); + } + return this; + } + + public void awaitStopped() { + this.state.awaitStopped(); + } + + public void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException { + this.state.awaitStopped(timeout, unit); + } + + public boolean isHealthy() { + for (Service service : this.services) { + if (service.isRunning()) continue; + return false; + } + return true; + } + + public ImmutableMultimap servicesByState() { + return this.state.servicesByState(); + } + + public ImmutableMap startupTimes() { + return this.state.startupTimes(); + } + + public String toString() { + return MoreObjects.toStringHelper(ServiceManager.class).add("services", Collections2.filter(this.services, Predicates.not(Predicates.instanceOf(NoOpService.class)))).toString(); + } + + private static final class EmptyServiceManagerWarning + extends Throwable { + private EmptyServiceManagerWarning() { + } + } + + private static final class NoOpService + extends AbstractService { + private NoOpService() { + } + + @Override + protected void doStart() { + this.notifyStarted(); + } + + @Override + protected void doStop() { + this.notifyStopped(); + } + } + + private static final class ServiceListener + extends Service.Listener { + final Service service; + final WeakReference state; + + ServiceListener(Service service, WeakReference state) { + this.service = service; + this.state = state; + } + + @Override + public void starting() { + ServiceManagerState state = (ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(this.service, Service.State.NEW, Service.State.STARTING); + if (!(this.service instanceof NoOpService)) { + logger.log(Level.FINE, "Starting {0}.", this.service); + } + } + } + + @Override + public void running() { + ServiceManagerState state = (ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(this.service, Service.State.STARTING, Service.State.RUNNING); + } + } + + @Override + public void stopping(Service.State from) { + ServiceManagerState state = (ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(this.service, from, Service.State.STOPPING); + } + } + + @Override + public void terminated(Service.State from) { + ServiceManagerState state = (ServiceManagerState)this.state.get(); + if (state != null) { + if (!(this.service instanceof NoOpService)) { + logger.log(Level.FINE, "Service {0} has terminated. Previous state was: {1}", new Object[]{this.service, from}); + } + state.transitionService(this.service, from, Service.State.TERMINATED); + } + } + + @Override + public void failed(Service.State from, Throwable failure) { + ServiceManagerState state = (ServiceManagerState)this.state.get(); + if (state != null) { + if (!(this.service instanceof NoOpService)) { + String string = String.valueOf(String.valueOf(this.service)); + String string2 = String.valueOf(String.valueOf((Object)from)); + logger.log(Level.SEVERE, new StringBuilder(34 + string.length() + string2.length()).append("Service ").append(string).append(" has failed in the ").append(string2).append(" state.").toString(), failure); + } + state.transitionService(this.service, from, Service.State.FAILED); + } + } + } + + private static final class ServiceManagerState { + final Monitor monitor = new Monitor(); + @GuardedBy(value="monitor") + final SetMultimap servicesByState = Multimaps.newSetMultimap(new EnumMap(Service.State.class), new Supplier>(){ + + @Override + public Set get() { + return Sets.newLinkedHashSet(); + } + }); + @GuardedBy(value="monitor") + final Multiset states = this.servicesByState.keys(); + @GuardedBy(value="monitor") + final Map startupTimers = Maps.newIdentityHashMap(); + @GuardedBy(value="monitor") + boolean ready; + @GuardedBy(value="monitor") + boolean transitioned; + final int numberOfServices; + final Monitor.Guard awaitHealthGuard = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return ServiceManagerState.this.states.count((Object)Service.State.RUNNING) == ServiceManagerState.this.numberOfServices || ServiceManagerState.this.states.contains((Object)Service.State.STOPPING) || ServiceManagerState.this.states.contains((Object)Service.State.TERMINATED) || ServiceManagerState.this.states.contains((Object)Service.State.FAILED); + } + }; + final Monitor.Guard stoppedGuard = new Monitor.Guard(this.monitor){ + + @Override + public boolean isSatisfied() { + return ServiceManagerState.this.states.count((Object)Service.State.TERMINATED) + ServiceManagerState.this.states.count((Object)Service.State.FAILED) == ServiceManagerState.this.numberOfServices; + } + }; + @GuardedBy(value="monitor") + final List> listeners = Collections.synchronizedList(new ArrayList()); + + ServiceManagerState(ImmutableCollection services) { + this.numberOfServices = services.size(); + this.servicesByState.putAll(Service.State.NEW, services); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void tryStartTiming(Service service) { + this.monitor.enter(); + try { + Stopwatch stopwatch = this.startupTimers.get(service); + if (stopwatch == null) { + this.startupTimers.put(service, Stopwatch.createStarted()); + } + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void markReady() { + block5: { + this.monitor.enter(); + try { + if (!this.transitioned) { + this.ready = true; + break block5; + } + ArrayList servicesInBadStates = Lists.newArrayList(); + for (Service service : this.servicesByState().values()) { + if (service.state() == Service.State.NEW) continue; + servicesInBadStates.add(service); + } + String string = String.valueOf(String.valueOf("Services started transitioning asynchronously before the ServiceManager was constructed: ")); + String string2 = String.valueOf(String.valueOf(servicesInBadStates)); + throw new IllegalArgumentException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString()); + } + finally { + this.monitor.leave(); + } + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void addListener(Listener listener, Executor executor) { + Preconditions.checkNotNull(listener, "listener"); + Preconditions.checkNotNull(executor, "executor"); + this.monitor.enter(); + try { + if (!this.stoppedGuard.isSatisfied()) { + this.listeners.add(new ListenerCallQueue(listener, executor)); + } + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void awaitHealthy() { + this.monitor.enterWhenUninterruptibly(this.awaitHealthGuard); + try { + this.checkHealthy(); + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void awaitHealthy(long timeout, TimeUnit unit) throws TimeoutException { + this.monitor.enter(); + try { + if (!this.monitor.waitForUninterruptibly(this.awaitHealthGuard, timeout, unit)) { + String string = String.valueOf(String.valueOf("Timeout waiting for the services to become healthy. The following services have not started: ")); + String string2 = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.in(ImmutableSet.of(Service.State.NEW, Service.State.STARTING))))); + throw new TimeoutException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString()); + } + this.checkHealthy(); + } + finally { + this.monitor.leave(); + } + } + + void awaitStopped() { + this.monitor.enterWhenUninterruptibly(this.stoppedGuard); + this.monitor.leave(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException { + this.monitor.enter(); + try { + if (!this.monitor.waitForUninterruptibly(this.stoppedGuard, timeout, unit)) { + String string = String.valueOf(String.valueOf("Timeout waiting for the services to stop. The following services have not stopped: ")); + String string2 = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.not(Predicates.in(ImmutableSet.of(Service.State.TERMINATED, Service.State.FAILED)))))); + throw new TimeoutException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString()); + } + } + finally { + this.monitor.leave(); + } + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + ImmutableMultimap servicesByState() { + ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); + this.monitor.enter(); + try { + for (Map.Entry entry : this.servicesByState.entries()) { + if (entry.getValue() instanceof NoOpService) continue; + builder.put((Object)entry.getKey(), entry.getValue()); + } + } + finally { + this.monitor.leave(); + } + return builder.build(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + ImmutableMap startupTimes() { + ArrayList> loadTimes; + this.monitor.enter(); + try { + loadTimes = Lists.newArrayListWithCapacity(this.startupTimers.size()); + for (Map.Entry entry : this.startupTimers.entrySet()) { + Service service = entry.getKey(); + Stopwatch stopWatch = entry.getValue(); + if (stopWatch.isRunning() || service instanceof NoOpService) continue; + loadTimes.add(Maps.immutableEntry(service, stopWatch.elapsed(TimeUnit.MILLISECONDS))); + } + } + finally { + this.monitor.leave(); + } + Collections.sort(loadTimes, Ordering.natural().onResultOf(new Function, Long>(){ + + @Override + public Long apply(Map.Entry input) { + return input.getValue(); + } + })); + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Map.Entry entry : loadTimes) { + builder.put(entry); + } + return builder.build(); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + void transitionService(Service service, Service.State from, Service.State to) { + Preconditions.checkNotNull(service); + Preconditions.checkArgument(from != to); + this.monitor.enter(); + try { + this.transitioned = true; + if (!this.ready) { + return; + } + Preconditions.checkState(this.servicesByState.remove((Object)from, service), "Service %s not at the expected location in the state map %s", new Object[]{service, from}); + Preconditions.checkState(this.servicesByState.put(to, service), "Service %s in the state map unexpectedly at %s", new Object[]{service, to}); + Stopwatch stopwatch = this.startupTimers.get(service); + if (stopwatch == null) { + stopwatch = Stopwatch.createStarted(); + this.startupTimers.put(service, stopwatch); + } + if (to.compareTo(Service.State.RUNNING) >= 0 && stopwatch.isRunning()) { + stopwatch.stop(); + if (!(service instanceof NoOpService)) { + logger.log(Level.FINE, "Started {0} in {1}.", new Object[]{service, stopwatch}); + } + } + if (to == Service.State.FAILED) { + this.fireFailedListeners(service); + } + if (this.states.count((Object)Service.State.RUNNING) == this.numberOfServices) { + this.fireHealthyListeners(); + } else if (this.states.count((Object)Service.State.TERMINATED) + this.states.count((Object)Service.State.FAILED) == this.numberOfServices) { + this.fireStoppedListeners(); + } + } + finally { + this.monitor.leave(); + this.executeListeners(); + } + } + + @GuardedBy(value="monitor") + void fireStoppedListeners() { + STOPPED_CALLBACK.enqueueOn(this.listeners); + } + + @GuardedBy(value="monitor") + void fireHealthyListeners() { + HEALTHY_CALLBACK.enqueueOn(this.listeners); + } + + @GuardedBy(value="monitor") + void fireFailedListeners(final Service service) { + String string = String.valueOf(String.valueOf(service)); + new ListenerCallQueue.Callback(new StringBuilder(18 + string.length()).append("failed({service=").append(string).append("})").toString()){ + + @Override + void call(Listener listener) { + listener.failure(service); + } + }.enqueueOn(this.listeners); + } + + void executeListeners() { + Preconditions.checkState(!this.monitor.isOccupiedByCurrentThread(), "It is incorrect to execute listeners with the monitor held."); + for (int i = 0; i < this.listeners.size(); ++i) { + this.listeners.get(i).execute(); + } + } + + @GuardedBy(value="monitor") + void checkHealthy() { + if (this.states.count((Object)Service.State.RUNNING) != this.numberOfServices) { + String string = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.not(Predicates.equalTo(Service.State.RUNNING))))); + IllegalStateException exception = new IllegalStateException(new StringBuilder(79 + string.length()).append("Expected to be healthy after starting. The following services are not running: ").append(string).toString()); + throw exception; + } + } + } + + @Beta + public static abstract class Listener { + public void healthy() { + } + + public void stopped() { + } + + public void failure(Service service) { + } + } +} diff --git a/src/com/google/common/util/concurrent/SettableFuture.java b/src/com/google/common/util/concurrent/SettableFuture.java new file mode 100644 index 0000000..a385b49 --- /dev/null +++ b/src/com/google/common/util/concurrent/SettableFuture.java @@ -0,0 +1,27 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.AbstractFuture; +import javax.annotation.Nullable; + +public final class SettableFuture +extends AbstractFuture { + public static SettableFuture create() { + return new SettableFuture(); + } + + private SettableFuture() { + } + + @Override + public boolean set(@Nullable V value) { + return super.set(value); + } + + @Override + public boolean setException(Throwable throwable) { + return super.setException(throwable); + } +} diff --git a/src/com/google/common/util/concurrent/SimpleTimeLimiter.java b/src/com/google/common/util/concurrent/SimpleTimeLimiter.java new file mode 100644 index 0000000..cb0a15a --- /dev/null +++ b/src/com/google/common/util/concurrent/SimpleTimeLimiter.java @@ -0,0 +1,137 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.TimeLimiter; +import com.google.common.util.concurrent.UncheckedTimeoutException; +import com.google.common.util.concurrent.Uninterruptibles; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public final class SimpleTimeLimiter +implements TimeLimiter { + private final ExecutorService executor; + + public SimpleTimeLimiter(ExecutorService executor) { + this.executor = Preconditions.checkNotNull(executor); + } + + public SimpleTimeLimiter() { + this(Executors.newCachedThreadPool()); + } + + @Override + public T newProxy(final T target, Class interfaceType, final long timeoutDuration, final TimeUnit timeoutUnit) { + Preconditions.checkNotNull(target); + Preconditions.checkNotNull(interfaceType); + Preconditions.checkNotNull(timeoutUnit); + Preconditions.checkArgument(timeoutDuration > 0L, "bad timeout: %s", timeoutDuration); + Preconditions.checkArgument(interfaceType.isInterface(), "interfaceType must be an interface type"); + final Set interruptibleMethods = SimpleTimeLimiter.findInterruptibleMethods(interfaceType); + InvocationHandler handler = new InvocationHandler(){ + + @Override + public Object invoke(Object obj, final Method method, final Object[] args) throws Throwable { + Callable callable = new Callable(){ + + @Override + public Object call() throws Exception { + try { + return method.invoke(target, args); + } + catch (InvocationTargetException e) { + SimpleTimeLimiter.throwCause(e, false); + throw new AssertionError((Object)"can't get here"); + } + } + }; + return SimpleTimeLimiter.this.callWithTimeout(callable, timeoutDuration, timeoutUnit, interruptibleMethods.contains(method)); + } + }; + return SimpleTimeLimiter.newProxy(interfaceType, handler); + } + + @Override + public T callWithTimeout(Callable callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { + Preconditions.checkNotNull(callable); + Preconditions.checkNotNull(timeoutUnit); + Preconditions.checkArgument(timeoutDuration > 0L, "timeout must be positive: %s", timeoutDuration); + Future future = this.executor.submit(callable); + try { + if (amInterruptible) { + try { + return future.get(timeoutDuration, timeoutUnit); + } + catch (InterruptedException e) { + future.cancel(true); + throw e; + } + } + return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); + } + catch (ExecutionException e) { + throw SimpleTimeLimiter.throwCause(e, true); + } + catch (TimeoutException e) { + future.cancel(true); + throw new UncheckedTimeoutException(e); + } + } + + private static Exception throwCause(Exception e, boolean combineStackTraces) throws Exception { + Throwable cause = e.getCause(); + if (cause == null) { + throw e; + } + if (combineStackTraces) { + StackTraceElement[] combined = ObjectArrays.concat(cause.getStackTrace(), e.getStackTrace(), StackTraceElement.class); + cause.setStackTrace(combined); + } + if (cause instanceof Exception) { + throw (Exception)cause; + } + if (cause instanceof Error) { + throw (Error)cause; + } + throw e; + } + + private static Set findInterruptibleMethods(Class interfaceType) { + HashSet set = Sets.newHashSet(); + for (Method m : interfaceType.getMethods()) { + if (!SimpleTimeLimiter.declaresInterruptedEx(m)) continue; + set.add(m); + } + return set; + } + + private static boolean declaresInterruptedEx(Method method) { + for (Class exType : method.getExceptionTypes()) { + if (exType != InterruptedException.class) continue; + return true; + } + return false; + } + + private static T newProxy(Class interfaceType, InvocationHandler handler) { + Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[]{interfaceType}, handler); + return interfaceType.cast(object); + } +} diff --git a/src/com/google/common/util/concurrent/SmoothRateLimiter.java b/src/com/google/common/util/concurrent/SmoothRateLimiter.java new file mode 100644 index 0000000..0345542 --- /dev/null +++ b/src/com/google/common/util/concurrent/SmoothRateLimiter.java @@ -0,0 +1,121 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.RateLimiter; +import java.util.concurrent.TimeUnit; + +abstract class SmoothRateLimiter +extends RateLimiter { + double storedPermits; + double maxPermits; + double stableIntervalMicros; + private long nextFreeTicketMicros = 0L; + + private SmoothRateLimiter(RateLimiter.SleepingStopwatch stopwatch) { + super(stopwatch); + } + + @Override + final void doSetRate(double permitsPerSecond, long nowMicros) { + double stableIntervalMicros; + this.resync(nowMicros); + this.stableIntervalMicros = stableIntervalMicros = (double)TimeUnit.SECONDS.toMicros(1L) / permitsPerSecond; + this.doSetRate(permitsPerSecond, stableIntervalMicros); + } + + abstract void doSetRate(double var1, double var3); + + @Override + final double doGetRate() { + return (double)TimeUnit.SECONDS.toMicros(1L) / this.stableIntervalMicros; + } + + @Override + final long queryEarliestAvailable(long nowMicros) { + return this.nextFreeTicketMicros; + } + + @Override + final long reserveEarliestAvailable(int requiredPermits, long nowMicros) { + this.resync(nowMicros); + long returnValue = this.nextFreeTicketMicros; + double storedPermitsToSpend = Math.min((double)requiredPermits, this.storedPermits); + double freshPermits = (double)requiredPermits - storedPermitsToSpend; + long waitMicros = this.storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend) + (long)(freshPermits * this.stableIntervalMicros); + this.nextFreeTicketMicros += waitMicros; + this.storedPermits -= storedPermitsToSpend; + return returnValue; + } + + abstract long storedPermitsToWaitTime(double var1, double var3); + + private void resync(long nowMicros) { + if (nowMicros > this.nextFreeTicketMicros) { + this.storedPermits = Math.min(this.maxPermits, this.storedPermits + (double)(nowMicros - this.nextFreeTicketMicros) / this.stableIntervalMicros); + this.nextFreeTicketMicros = nowMicros; + } + } + + static final class SmoothBursty + extends SmoothRateLimiter { + final double maxBurstSeconds; + + SmoothBursty(RateLimiter.SleepingStopwatch stopwatch, double maxBurstSeconds) { + super(stopwatch); + this.maxBurstSeconds = maxBurstSeconds; + } + + @Override + void doSetRate(double permitsPerSecond, double stableIntervalMicros) { + double oldMaxPermits = this.maxPermits; + this.maxPermits = this.maxBurstSeconds * permitsPerSecond; + this.storedPermits = oldMaxPermits == Double.POSITIVE_INFINITY ? this.maxPermits : (oldMaxPermits == 0.0 ? 0.0 : this.storedPermits * this.maxPermits / oldMaxPermits); + } + + @Override + long storedPermitsToWaitTime(double storedPermits, double permitsToTake) { + return 0L; + } + } + + static final class SmoothWarmingUp + extends SmoothRateLimiter { + private final long warmupPeriodMicros; + private double slope; + private double halfPermits; + + SmoothWarmingUp(RateLimiter.SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit) { + super(stopwatch); + this.warmupPeriodMicros = timeUnit.toMicros(warmupPeriod); + } + + @Override + void doSetRate(double permitsPerSecond, double stableIntervalMicros) { + double oldMaxPermits = this.maxPermits; + this.maxPermits = (double)this.warmupPeriodMicros / stableIntervalMicros; + this.halfPermits = this.maxPermits / 2.0; + double coldIntervalMicros = stableIntervalMicros * 3.0; + this.slope = (coldIntervalMicros - stableIntervalMicros) / this.halfPermits; + this.storedPermits = oldMaxPermits == Double.POSITIVE_INFINITY ? 0.0 : (oldMaxPermits == 0.0 ? this.maxPermits : this.storedPermits * this.maxPermits / oldMaxPermits); + } + + @Override + long storedPermitsToWaitTime(double storedPermits, double permitsToTake) { + double availablePermitsAboveHalf = storedPermits - this.halfPermits; + long micros = 0L; + if (availablePermitsAboveHalf > 0.0) { + double permitsAboveHalfToTake = Math.min(availablePermitsAboveHalf, permitsToTake); + micros = (long)(permitsAboveHalfToTake * (this.permitsToTime(availablePermitsAboveHalf) + this.permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0); + permitsToTake -= permitsAboveHalfToTake; + } + micros = (long)((double)micros + this.stableIntervalMicros * permitsToTake); + return micros; + } + + private double permitsToTime(double permits) { + return this.stableIntervalMicros + permits * this.slope; + } + } +} diff --git a/src/com/google/common/util/concurrent/Striped.java b/src/com/google/common/util/concurrent/Striped.java new file mode 100644 index 0000000..2e25590 --- /dev/null +++ b/src/com/google/common/util/concurrent/Striped.java @@ -0,0 +1,301 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.MapMaker; +import com.google.common.math.IntMath; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +@Beta +public abstract class Striped { + private static final int LARGE_LAZY_CUTOFF = 1024; + private static final Supplier READ_WRITE_LOCK_SUPPLIER = new Supplier(){ + + @Override + public ReadWriteLock get() { + return new ReentrantReadWriteLock(); + } + }; + private static final int ALL_SET = -1; + + private Striped() { + } + + public abstract L get(Object var1); + + public abstract L getAt(int var1); + + abstract int indexFor(Object var1); + + public abstract int size(); + + public Iterable bulkGet(Iterable keys) { + Object[] array = Iterables.toArray(keys, Object.class); + if (array.length == 0) { + return ImmutableList.of(); + } + int[] stripes = new int[array.length]; + for (int i = 0; i < array.length; ++i) { + stripes[i] = this.indexFor(array[i]); + } + Arrays.sort(stripes); + int previousStripe = stripes[0]; + array[0] = this.getAt(previousStripe); + for (int i = 1; i < array.length; ++i) { + int currentStripe = stripes[i]; + if (currentStripe == previousStripe) { + array[i] = array[i - 1]; + continue; + } + array[i] = this.getAt(currentStripe); + previousStripe = currentStripe; + } + List asList = Arrays.asList(array); + return Collections.unmodifiableList(asList); + } + + public static Striped lock(int stripes) { + return new CompactStriped(stripes, new Supplier(){ + + @Override + public Lock get() { + return new PaddedLock(); + } + }); + } + + public static Striped lazyWeakLock(int stripes) { + return Striped.lazy(stripes, new Supplier(){ + + @Override + public Lock get() { + return new ReentrantLock(false); + } + }); + } + + private static Striped lazy(int stripes, Supplier supplier) { + return stripes < 1024 ? new SmallLazyStriped(stripes, supplier) : new LargeLazyStriped(stripes, supplier); + } + + public static Striped semaphore(int stripes, final int permits) { + return new CompactStriped(stripes, new Supplier(){ + + @Override + public Semaphore get() { + return new PaddedSemaphore(permits); + } + }); + } + + public static Striped lazyWeakSemaphore(int stripes, final int permits) { + return Striped.lazy(stripes, new Supplier(){ + + @Override + public Semaphore get() { + return new Semaphore(permits, false); + } + }); + } + + public static Striped readWriteLock(int stripes) { + return new CompactStriped(stripes, READ_WRITE_LOCK_SUPPLIER); + } + + public static Striped lazyWeakReadWriteLock(int stripes) { + return Striped.lazy(stripes, READ_WRITE_LOCK_SUPPLIER); + } + + private static int ceilToPowerOfTwo(int x) { + return 1 << IntMath.log2(x, RoundingMode.CEILING); + } + + private static int smear(int hashCode) { + hashCode ^= hashCode >>> 20 ^ hashCode >>> 12; + return hashCode ^ hashCode >>> 7 ^ hashCode >>> 4; + } + + private static class PaddedSemaphore + extends Semaphore { + long q1; + long q2; + long q3; + + PaddedSemaphore(int permits) { + super(permits, false); + } + } + + private static class PaddedLock + extends ReentrantLock { + long q1; + long q2; + long q3; + + PaddedLock() { + super(false); + } + } + + @VisibleForTesting + static class LargeLazyStriped + extends PowerOfTwoStriped { + final ConcurrentMap locks; + final Supplier supplier; + final int size; + + LargeLazyStriped(int stripes, Supplier supplier) { + super(stripes); + this.size = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1; + this.supplier = supplier; + this.locks = new MapMaker().weakValues().makeMap(); + } + + @Override + public L getAt(int index) { + Object existing; + if (this.size != Integer.MAX_VALUE) { + Preconditions.checkElementIndex(index, this.size()); + } + if ((existing = this.locks.get(index)) != null) { + return (L)existing; + } + L created = this.supplier.get(); + existing = this.locks.putIfAbsent(index, created); + return (L)MoreObjects.firstNonNull(existing, created); + } + + @Override + public int size() { + return this.size; + } + } + + @VisibleForTesting + static class SmallLazyStriped + extends PowerOfTwoStriped { + final AtomicReferenceArray> locks; + final Supplier supplier; + final int size; + final ReferenceQueue queue = new ReferenceQueue(); + + SmallLazyStriped(int stripes, Supplier supplier) { + super(stripes); + this.size = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1; + this.locks = new AtomicReferenceArray(this.size); + this.supplier = supplier; + } + + @Override + public L getAt(int index) { + ArrayReference existingRef; + L existing; + if (this.size != Integer.MAX_VALUE) { + Preconditions.checkElementIndex(index, this.size()); + } + L l = existing = (existingRef = this.locks.get(index)) == null ? null : (L)existingRef.get(); + if (existing != null) { + return existing; + } + L created = this.supplier.get(); + ArrayReference newRef = new ArrayReference(created, index, this.queue); + while (!this.locks.compareAndSet(index, existingRef, newRef)) { + existingRef = this.locks.get(index); + existing = existingRef == null ? null : (L)existingRef.get(); + if (existing == null) continue; + return existing; + } + this.drainQueue(); + return created; + } + + private void drainQueue() { + Reference ref; + while ((ref = this.queue.poll()) != null) { + ArrayReference arrayRef = (ArrayReference)ref; + this.locks.compareAndSet(arrayRef.index, arrayRef, null); + } + } + + @Override + public int size() { + return this.size; + } + + private static final class ArrayReference + extends WeakReference { + final int index; + + ArrayReference(L referent, int index, ReferenceQueue queue) { + super(referent, queue); + this.index = index; + } + } + } + + private static class CompactStriped + extends PowerOfTwoStriped { + private final Object[] array; + + private CompactStriped(int stripes, Supplier supplier) { + super(stripes); + Preconditions.checkArgument(stripes <= 0x40000000, "Stripes must be <= 2^30)"); + this.array = new Object[this.mask + 1]; + for (int i = 0; i < this.array.length; ++i) { + this.array[i] = supplier.get(); + } + } + + @Override + public L getAt(int index) { + return (L)this.array[index]; + } + + @Override + public int size() { + return this.array.length; + } + } + + private static abstract class PowerOfTwoStriped + extends Striped { + final int mask; + + PowerOfTwoStriped(int stripes) { + Preconditions.checkArgument(stripes > 0, "Stripes must be positive"); + this.mask = stripes > 0x40000000 ? -1 : Striped.ceilToPowerOfTwo(stripes) - 1; + } + + @Override + final int indexFor(Object key) { + int hash = Striped.smear(key.hashCode()); + return hash & this.mask; + } + + @Override + public final L get(Object key) { + return this.getAt(this.indexFor(key)); + } + } +} diff --git a/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java b/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java new file mode 100644 index 0000000..80b0c49 --- /dev/null +++ b/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java @@ -0,0 +1,78 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +public final class ThreadFactoryBuilder { + private String nameFormat = null; + private Boolean daemon = null; + private Integer priority = null; + private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = null; + private ThreadFactory backingThreadFactory = null; + + public ThreadFactoryBuilder setNameFormat(String nameFormat) { + String.format(nameFormat, 0); + this.nameFormat = nameFormat; + return this; + } + + public ThreadFactoryBuilder setDaemon(boolean daemon) { + this.daemon = daemon; + return this; + } + + public ThreadFactoryBuilder setPriority(int priority) { + Preconditions.checkArgument(priority >= 1, "Thread priority (%s) must be >= %s", priority, 1); + Preconditions.checkArgument(priority <= 10, "Thread priority (%s) must be <= %s", priority, 10); + this.priority = priority; + return this; + } + + public ThreadFactoryBuilder setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) { + this.uncaughtExceptionHandler = Preconditions.checkNotNull(uncaughtExceptionHandler); + return this; + } + + public ThreadFactoryBuilder setThreadFactory(ThreadFactory backingThreadFactory) { + this.backingThreadFactory = Preconditions.checkNotNull(backingThreadFactory); + return this; + } + + public ThreadFactory build() { + return ThreadFactoryBuilder.build(this); + } + + private static ThreadFactory build(ThreadFactoryBuilder builder) { + final String nameFormat = builder.nameFormat; + final Boolean daemon = builder.daemon; + final Integer priority = builder.priority; + final Thread.UncaughtExceptionHandler uncaughtExceptionHandler = builder.uncaughtExceptionHandler; + final ThreadFactory backingThreadFactory = builder.backingThreadFactory != null ? builder.backingThreadFactory : Executors.defaultThreadFactory(); + final AtomicLong count = nameFormat != null ? new AtomicLong(0L) : null; + return new ThreadFactory(){ + + @Override + public Thread newThread(Runnable runnable) { + Thread thread = backingThreadFactory.newThread(runnable); + if (nameFormat != null) { + thread.setName(String.format(nameFormat, count.getAndIncrement())); + } + if (daemon != null) { + thread.setDaemon(daemon); + } + if (priority != null) { + thread.setPriority(priority); + } + if (uncaughtExceptionHandler != null) { + thread.setUncaughtExceptionHandler(uncaughtExceptionHandler); + } + return thread; + } + }; + } +} diff --git a/src/com/google/common/util/concurrent/TimeLimiter.java b/src/com/google/common/util/concurrent/TimeLimiter.java new file mode 100644 index 0000000..1180de6 --- /dev/null +++ b/src/com/google/common/util/concurrent/TimeLimiter.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +@Beta +public interface TimeLimiter { + public T newProxy(T var1, Class var2, long var3, TimeUnit var5); + + public T callWithTimeout(Callable var1, long var2, TimeUnit var4, boolean var5) throws Exception; +} diff --git a/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java new file mode 100644 index 0000000..780801a --- /dev/null +++ b/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java @@ -0,0 +1,45 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.VisibleForTesting; +import java.util.logging.Level; +import java.util.logging.Logger; + +public final class UncaughtExceptionHandlers { + private UncaughtExceptionHandlers() { + } + + public static Thread.UncaughtExceptionHandler systemExit() { + return new Exiter(Runtime.getRuntime()); + } + + @VisibleForTesting + static final class Exiter + implements Thread.UncaughtExceptionHandler { + private static final Logger logger = Logger.getLogger(Exiter.class.getName()); + private final Runtime runtime; + + Exiter(Runtime runtime) { + this.runtime = runtime; + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public void uncaughtException(Thread t, Throwable e) { + try { + logger.log(Level.SEVERE, String.format("Caught an exception in %s. Shutting down.", t), e); + } + catch (Throwable errorInLogging) { + System.err.println(e.getMessage()); + System.err.println(errorInLogging.getMessage()); + } + finally { + this.runtime.exit(1); + } + } + } +} diff --git a/src/com/google/common/util/concurrent/UncheckedExecutionException.java b/src/com/google/common/util/concurrent/UncheckedExecutionException.java new file mode 100644 index 0000000..aeb1ce8 --- /dev/null +++ b/src/com/google/common/util/concurrent/UncheckedExecutionException.java @@ -0,0 +1,28 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public class UncheckedExecutionException +extends RuntimeException { + private static final long serialVersionUID = 0L; + + protected UncheckedExecutionException() { + } + + protected UncheckedExecutionException(@Nullable String message) { + super(message); + } + + public UncheckedExecutionException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } + + public UncheckedExecutionException(@Nullable Throwable cause) { + super(cause); + } +} diff --git a/src/com/google/common/util/concurrent/UncheckedTimeoutException.java b/src/com/google/common/util/concurrent/UncheckedTimeoutException.java new file mode 100644 index 0000000..dd0541b --- /dev/null +++ b/src/com/google/common/util/concurrent/UncheckedTimeoutException.java @@ -0,0 +1,26 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import javax.annotation.Nullable; + +public class UncheckedTimeoutException +extends RuntimeException { + private static final long serialVersionUID = 0L; + + public UncheckedTimeoutException() { + } + + public UncheckedTimeoutException(@Nullable String message) { + super(message); + } + + public UncheckedTimeoutException(@Nullable Throwable cause) { + super(cause); + } + + public UncheckedTimeoutException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } +} diff --git a/src/com/google/common/util/concurrent/Uninterruptibles.java b/src/com/google/common/util/concurrent/Uninterruptibles.java new file mode 100644 index 0000000..5450dab --- /dev/null +++ b/src/com/google/common/util/concurrent/Uninterruptibles.java @@ -0,0 +1,250 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public final class Uninterruptibles { + public static void awaitUninterruptibly(CountDownLatch latch) { + boolean interrupted = false; + while (true) { + try { + latch.await(); + return; + } + catch (InterruptedException e) { + interrupted = true; + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static boolean awaitUninterruptibly(CountDownLatch latch, long timeout, TimeUnit unit) { + boolean interrupted = false; + try { + long remainingNanos = unit.toNanos(timeout); + long end = System.nanoTime() + remainingNanos; + while (true) { + try { + boolean bl = latch.await(remainingNanos, TimeUnit.NANOSECONDS); + return bl; + } + catch (InterruptedException e) { + interrupted = true; + remainingNanos = end - System.nanoTime(); + continue; + } + break; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static void joinUninterruptibly(Thread toJoin) { + boolean interrupted = false; + while (true) { + try { + toJoin.join(); + return; + } + catch (InterruptedException e) { + interrupted = true; + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static V getUninterruptibly(Future future) throws ExecutionException { + boolean interrupted = false; + while (true) { + try { + V v = future.get(); + return v; + } + catch (InterruptedException e) { + interrupted = true; + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static V getUninterruptibly(Future future, long timeout, TimeUnit unit) throws ExecutionException, TimeoutException { + boolean interrupted = false; + try { + long remainingNanos = unit.toNanos(timeout); + long end = System.nanoTime() + remainingNanos; + while (true) { + V v; + try { + v = future.get(remainingNanos, TimeUnit.NANOSECONDS); + } + catch (InterruptedException e) { + interrupted = true; + remainingNanos = end - System.nanoTime(); + continue; + } + return v; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static void joinUninterruptibly(Thread toJoin, long timeout, TimeUnit unit) { + Preconditions.checkNotNull(toJoin); + boolean interrupted = false; + try { + long remainingNanos = unit.toNanos(timeout); + long end = System.nanoTime() + remainingNanos; + while (true) { + try { + TimeUnit.NANOSECONDS.timedJoin(toJoin, remainingNanos); + return; + } + catch (InterruptedException e) { + interrupted = true; + remainingNanos = end - System.nanoTime(); + continue; + } + break; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static E takeUninterruptibly(BlockingQueue queue) { + boolean interrupted = false; + while (true) { + try { + E e = queue.take(); + return e; + } + catch (InterruptedException e) { + interrupted = true; + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static void putUninterruptibly(BlockingQueue queue, E element) { + boolean interrupted = false; + while (true) { + try { + queue.put(element); + return; + } + catch (InterruptedException e) { + interrupted = true; + continue; + } + break; + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) { + boolean interrupted = false; + try { + long remainingNanos = unit.toNanos(sleepFor); + long end = System.nanoTime() + remainingNanos; + while (true) { + try { + TimeUnit.NANOSECONDS.sleep(remainingNanos); + return; + } + catch (InterruptedException e) { + interrupted = true; + remainingNanos = end - System.nanoTime(); + continue; + } + break; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public static boolean tryAcquireUninterruptibly(Semaphore semaphore, long timeout, TimeUnit unit) { + return Uninterruptibles.tryAcquireUninterruptibly(semaphore, 1, timeout, unit); + } + + public static boolean tryAcquireUninterruptibly(Semaphore semaphore, int permits, long timeout, TimeUnit unit) { + boolean interrupted = false; + try { + long remainingNanos = unit.toNanos(timeout); + long end = System.nanoTime() + remainingNanos; + while (true) { + try { + boolean bl = semaphore.tryAcquire(permits, remainingNanos, TimeUnit.NANOSECONDS); + return bl; + } + catch (InterruptedException e) { + interrupted = true; + remainingNanos = end - System.nanoTime(); + continue; + } + break; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + private Uninterruptibles() { + } +} diff --git a/src/com/google/common/util/concurrent/WrappingExecutorService.java b/src/com/google/common/util/concurrent/WrappingExecutorService.java new file mode 100644 index 0000000..be4b6e3 --- /dev/null +++ b/src/com/google/common/util/concurrent/WrappingExecutorService.java @@ -0,0 +1,117 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +abstract class WrappingExecutorService +implements ExecutorService { + private final ExecutorService delegate; + + protected WrappingExecutorService(ExecutorService delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + protected abstract Callable wrapTask(Callable var1); + + protected Runnable wrapTask(Runnable command) { + final Callable wrapped = this.wrapTask(Executors.callable(command, null)); + return new Runnable(){ + + @Override + public void run() { + try { + wrapped.call(); + } + catch (Exception e) { + Throwables.propagate(e); + } + } + }; + } + + private final ImmutableList> wrapTasks(Collection> tasks) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Callable task : tasks) { + builder.add(this.wrapTask(task)); + } + return builder.build(); + } + + @Override + public final void execute(Runnable command) { + this.delegate.execute(this.wrapTask(command)); + } + + @Override + public final Future submit(Callable task) { + return this.delegate.submit(this.wrapTask(Preconditions.checkNotNull(task))); + } + + @Override + public final Future submit(Runnable task) { + return this.delegate.submit(this.wrapTask(task)); + } + + @Override + public final Future submit(Runnable task, T result) { + return this.delegate.submit(this.wrapTask(task), result); + } + + @Override + public final List> invokeAll(Collection> tasks) throws InterruptedException { + return this.delegate.invokeAll(this.wrapTasks(tasks)); + } + + @Override + public final List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate.invokeAll(this.wrapTasks(tasks), timeout, unit); + } + + @Override + public final T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { + return this.delegate.invokeAny(this.wrapTasks(tasks)); + } + + @Override + public final T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return this.delegate.invokeAny(this.wrapTasks(tasks), timeout, unit); + } + + @Override + public final void shutdown() { + this.delegate.shutdown(); + } + + @Override + public final List shutdownNow() { + return this.delegate.shutdownNow(); + } + + @Override + public final boolean isShutdown() { + return this.delegate.isShutdown(); + } + + @Override + public final boolean isTerminated() { + return this.delegate.isTerminated(); + } + + @Override + public final boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return this.delegate.awaitTermination(timeout, unit); + } +} diff --git a/src/com/google/common/util/concurrent/WrappingScheduledExecutorService.java b/src/com/google/common/util/concurrent/WrappingScheduledExecutorService.java new file mode 100644 index 0000000..0418274 --- /dev/null +++ b/src/com/google/common/util/concurrent/WrappingScheduledExecutorService.java @@ -0,0 +1,41 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.util.concurrent; + +import com.google.common.util.concurrent.WrappingExecutorService; +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +abstract class WrappingScheduledExecutorService +extends WrappingExecutorService +implements ScheduledExecutorService { + final ScheduledExecutorService delegate; + + protected WrappingScheduledExecutorService(ScheduledExecutorService delegate) { + super(delegate); + this.delegate = delegate; + } + + @Override + public final ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { + return this.delegate.schedule(this.wrapTask(command), delay, unit); + } + + @Override + public final ScheduledFuture schedule(Callable task, long delay, TimeUnit unit) { + return this.delegate.schedule(this.wrapTask(task), delay, unit); + } + + @Override + public final ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { + return this.delegate.scheduleAtFixedRate(this.wrapTask(command), initialDelay, period, unit); + } + + @Override + public final ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { + return this.delegate.scheduleWithFixedDelay(this.wrapTask(command), initialDelay, delay, unit); + } +} diff --git a/src/com/google/common/util/concurrent/package-info.java b/src/com/google/common/util/concurrent/package-info.java new file mode 100644 index 0000000..aecac94 --- /dev/null +++ b/src/com/google/common/util/concurrent/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.util.concurrent; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/common/xml/XmlEscapers.java b/src/com/google/common/xml/XmlEscapers.java new file mode 100644 index 0000000..fa194d6 --- /dev/null +++ b/src/com/google/common/xml/XmlEscapers.java @@ -0,0 +1,51 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.common.xml; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; + +@Beta +@GwtCompatible +public class XmlEscapers { + private static final char MIN_ASCII_CONTROL_CHAR = '\u0000'; + private static final char MAX_ASCII_CONTROL_CHAR = '\u001f'; + private static final Escaper XML_ESCAPER; + private static final Escaper XML_CONTENT_ESCAPER; + private static final Escaper XML_ATTRIBUTE_ESCAPER; + + private XmlEscapers() { + } + + public static Escaper xmlContentEscaper() { + return XML_CONTENT_ESCAPER; + } + + public static Escaper xmlAttributeEscaper() { + return XML_ATTRIBUTE_ESCAPER; + } + + static { + Escapers.Builder builder = Escapers.builder(); + builder.setSafeRange('\u0000', '\ufffd'); + builder.setUnsafeReplacement("\ufffd"); + for (char c = '\u0000'; c <= '\u001f'; c = (char)((char)(c + 1))) { + if (c == 9 || c == 10 || c == 13) continue; + builder.addEscape(c, "\ufffd"); + } + builder.addEscape('&', "&"); + builder.addEscape('<', "<"); + builder.addEscape('>', ">"); + XML_CONTENT_ESCAPER = builder.build(); + builder.addEscape('\'', "'"); + builder.addEscape('\"', """); + XML_ESCAPER = builder.build(); + builder.addEscape('\t', " "); + builder.addEscape('\n', " "); + builder.addEscape('\r', " "); + XML_ATTRIBUTE_ESCAPER = builder.build(); + } +} diff --git a/src/com/google/common/xml/package-info.java b/src/com/google/common/xml/package-info.java new file mode 100644 index 0000000..cf5d076 --- /dev/null +++ b/src/com/google/common/xml/package-info.java @@ -0,0 +1,8 @@ +/* + * Decompiled with CFR 0.152. + */ +@ParametersAreNonnullByDefault +package com.google.common.xml; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/src/com/google/gson/DefaultDateTypeAdapter.java b/src/com/google/gson/DefaultDateTypeAdapter.java new file mode 100644 index 0000000..1e7742b --- /dev/null +++ b/src/com/google/gson/DefaultDateTypeAdapter.java @@ -0,0 +1,114 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonSyntaxException; +import java.lang.reflect.Type; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +final class DefaultDateTypeAdapter +implements JsonSerializer, +JsonDeserializer { + private final DateFormat enUsFormat; + private final DateFormat localFormat; + private final DateFormat iso8601Format; + + DefaultDateTypeAdapter() { + this(DateFormat.getDateTimeInstance(2, 2, Locale.US), DateFormat.getDateTimeInstance(2, 2)); + } + + DefaultDateTypeAdapter(String datePattern) { + this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); + } + + DefaultDateTypeAdapter(int style) { + this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); + } + + public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { + this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), DateFormat.getDateTimeInstance(dateStyle, timeStyle)); + } + + DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { + this.enUsFormat = enUsFormat; + this.localFormat = localFormat; + this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + /* + * WARNING - Removed try catching itself - possible behaviour change. + */ + @Override + public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { + DateFormat dateFormat = this.localFormat; + synchronized (dateFormat) { + String dateFormatAsString = this.enUsFormat.format(src); + return new JsonPrimitive(dateFormatAsString); + } + } + + @Override + public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (!(json instanceof JsonPrimitive)) { + throw new JsonParseException("The date should be a string value"); + } + Date date = this.deserializeToDate(json); + if (typeOfT == Date.class) { + return date; + } + if (typeOfT == Timestamp.class) { + return new Timestamp(date.getTime()); + } + if (typeOfT == java.sql.Date.class) { + return new java.sql.Date(date.getTime()); + } + throw new IllegalArgumentException(this.getClass() + " cannot deserialize to " + typeOfT); + } + + private Date deserializeToDate(JsonElement json) { + DateFormat dateFormat = this.localFormat; + synchronized (dateFormat) { + try { + return this.localFormat.parse(json.getAsString()); + } + catch (ParseException ignored) { + try { + return this.enUsFormat.parse(json.getAsString()); + } + catch (ParseException ignored2) { + try { + return this.iso8601Format.parse(json.getAsString()); + } + catch (ParseException e) { + throw new JsonSyntaxException(json.getAsString(), e); + } + } + } + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(DefaultDateTypeAdapter.class.getSimpleName()); + sb.append('(').append(this.localFormat.getClass().getSimpleName()).append(')'); + return sb.toString(); + } +} diff --git a/src/com/google/gson/ExclusionStrategy.java b/src/com/google/gson/ExclusionStrategy.java new file mode 100644 index 0000000..16cdfaf --- /dev/null +++ b/src/com/google/gson/ExclusionStrategy.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.FieldAttributes; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface ExclusionStrategy { + public boolean shouldSkipField(FieldAttributes var1); + + public boolean shouldSkipClass(Class var1); +} diff --git a/src/com/google/gson/FieldAttributes.java b/src/com/google/gson/FieldAttributes.java new file mode 100644 index 0000000..9d08991 --- /dev/null +++ b/src/com/google/gson/FieldAttributes.java @@ -0,0 +1,59 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.internal.$Gson$Preconditions; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class FieldAttributes { + private final Field field; + + public FieldAttributes(Field f) { + $Gson$Preconditions.checkNotNull(f); + this.field = f; + } + + public Class getDeclaringClass() { + return this.field.getDeclaringClass(); + } + + public String getName() { + return this.field.getName(); + } + + public Type getDeclaredType() { + return this.field.getGenericType(); + } + + public Class getDeclaredClass() { + return this.field.getType(); + } + + public T getAnnotation(Class annotation) { + return this.field.getAnnotation(annotation); + } + + public Collection getAnnotations() { + return Arrays.asList(this.field.getAnnotations()); + } + + public boolean hasModifier(int modifier) { + return (this.field.getModifiers() & modifier) != 0; + } + + Object get(Object instance) throws IllegalAccessException { + return this.field.get(instance); + } + + boolean isSynthetic() { + return this.field.isSynthetic(); + } +} diff --git a/src/com/google/gson/FieldNamingPolicy.java b/src/com/google/gson/FieldNamingPolicy.java new file mode 100644 index 0000000..8054d52 --- /dev/null +++ b/src/com/google/gson/FieldNamingPolicy.java @@ -0,0 +1,83 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.FieldNamingStrategy; +import java.lang.reflect.Field; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public enum FieldNamingPolicy implements FieldNamingStrategy +{ + IDENTITY{ + + public String translateName(Field f) { + return f.getName(); + } + } + , + UPPER_CAMEL_CASE{ + + public String translateName(Field f) { + return FieldNamingPolicy.upperCaseFirstLetter(f.getName()); + } + } + , + UPPER_CAMEL_CASE_WITH_SPACES{ + + public String translateName(Field f) { + return FieldNamingPolicy.upperCaseFirstLetter(FieldNamingPolicy.separateCamelCase(f.getName(), " ")); + } + } + , + LOWER_CASE_WITH_UNDERSCORES{ + + public String translateName(Field f) { + return FieldNamingPolicy.separateCamelCase(f.getName(), "_").toLowerCase(); + } + } + , + LOWER_CASE_WITH_DASHES{ + + public String translateName(Field f) { + return FieldNamingPolicy.separateCamelCase(f.getName(), "-").toLowerCase(); + } + }; + + + private static String separateCamelCase(String name, String separator) { + StringBuilder translation = new StringBuilder(); + for (int i = 0; i < name.length(); ++i) { + char character = name.charAt(i); + if (Character.isUpperCase(character) && translation.length() != 0) { + translation.append(separator); + } + translation.append(character); + } + return translation.toString(); + } + + private static String upperCaseFirstLetter(String name) { + StringBuilder fieldNameBuilder = new StringBuilder(); + int index = 0; + char firstCharacter = name.charAt(index); + while (index < name.length() - 1 && !Character.isLetter(firstCharacter)) { + fieldNameBuilder.append(firstCharacter); + firstCharacter = name.charAt(++index); + } + if (index == name.length()) { + return fieldNameBuilder.toString(); + } + if (!Character.isUpperCase(firstCharacter)) { + String modifiedTarget = FieldNamingPolicy.modifyString(Character.toUpperCase(firstCharacter), name, ++index); + return fieldNameBuilder.append(modifiedTarget).toString(); + } + return name; + } + + private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) { + return indexOfSubstring < srcString.length() ? firstCharacter + srcString.substring(indexOfSubstring) : String.valueOf(firstCharacter); + } +} diff --git a/src/com/google/gson/FieldNamingStrategy.java b/src/com/google/gson/FieldNamingStrategy.java new file mode 100644 index 0000000..f9b02ef --- /dev/null +++ b/src/com/google/gson/FieldNamingStrategy.java @@ -0,0 +1,10 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import java.lang.reflect.Field; + +public interface FieldNamingStrategy { + public String translateName(Field var1); +} diff --git a/src/com/google/gson/Gson.java b/src/com/google/gson/Gson.java new file mode 100644 index 0000000..08ca301 --- /dev/null +++ b/src/com/google/gson/Gson.java @@ -0,0 +1,514 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.FieldNamingStrategy; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSyntaxException; +import com.google.gson.LongSerializationPolicy; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.Primitives; +import com.google.gson.internal.Streams; +import com.google.gson.internal.bind.ArrayTypeAdapter; +import com.google.gson.internal.bind.CollectionTypeAdapterFactory; +import com.google.gson.internal.bind.DateTypeAdapter; +import com.google.gson.internal.bind.JsonTreeReader; +import com.google.gson.internal.bind.JsonTreeWriter; +import com.google.gson.internal.bind.MapTypeAdapterFactory; +import com.google.gson.internal.bind.ObjectTypeAdapter; +import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; +import com.google.gson.internal.bind.SqlDateTypeAdapter; +import com.google.gson.internal.bind.TimeTypeAdapter; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class Gson { + static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; + private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; + private final ThreadLocal, FutureTypeAdapter>> calls = new ThreadLocal(); + private final Map, TypeAdapter> typeTokenCache = Collections.synchronizedMap(new HashMap()); + private final List factories; + private final ConstructorConstructor constructorConstructor; + private final boolean serializeNulls; + private final boolean htmlSafe; + private final boolean generateNonExecutableJson; + private final boolean prettyPrinting; + final JsonDeserializationContext deserializationContext = new JsonDeserializationContext(){ + + @Override + public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException { + return Gson.this.fromJson(json, typeOfT); + } + }; + final JsonSerializationContext serializationContext = new JsonSerializationContext(){ + + public JsonElement serialize(Object src) { + return Gson.this.toJsonTree(src); + } + + public JsonElement serialize(Object src, Type typeOfSrc) { + return Gson.this.toJsonTree(src, typeOfSrc); + } + }; + + public Gson() { + this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, Collections.emptyMap(), false, false, false, true, false, false, LongSerializationPolicy.DEFAULT, Collections.emptyList()); + } + + Gson(Excluder excluder, FieldNamingStrategy fieldNamingPolicy, Map> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, List typeAdapterFactories) { + this.constructorConstructor = new ConstructorConstructor(instanceCreators); + this.serializeNulls = serializeNulls; + this.generateNonExecutableJson = generateNonExecutableGson; + this.htmlSafe = htmlSafe; + this.prettyPrinting = prettyPrinting; + ArrayList factories = new ArrayList(); + factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); + factories.add(ObjectTypeAdapter.FACTORY); + factories.add(excluder); + factories.addAll(typeAdapterFactories); + factories.add(TypeAdapters.STRING_FACTORY); + factories.add(TypeAdapters.INTEGER_FACTORY); + factories.add(TypeAdapters.BOOLEAN_FACTORY); + factories.add(TypeAdapters.BYTE_FACTORY); + factories.add(TypeAdapters.SHORT_FACTORY); + factories.add(TypeAdapters.newFactory(Long.TYPE, Long.class, this.longAdapter(longSerializationPolicy))); + factories.add(TypeAdapters.newFactory(Double.TYPE, Double.class, this.doubleAdapter(serializeSpecialFloatingPointValues))); + factories.add(TypeAdapters.newFactory(Float.TYPE, Float.class, this.floatAdapter(serializeSpecialFloatingPointValues))); + factories.add(TypeAdapters.NUMBER_FACTORY); + factories.add(TypeAdapters.CHARACTER_FACTORY); + factories.add(TypeAdapters.STRING_BUILDER_FACTORY); + factories.add(TypeAdapters.STRING_BUFFER_FACTORY); + factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); + factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); + factories.add(TypeAdapters.URL_FACTORY); + factories.add(TypeAdapters.URI_FACTORY); + factories.add(TypeAdapters.UUID_FACTORY); + factories.add(TypeAdapters.LOCALE_FACTORY); + factories.add(TypeAdapters.INET_ADDRESS_FACTORY); + factories.add(TypeAdapters.BIT_SET_FACTORY); + factories.add(DateTypeAdapter.FACTORY); + factories.add(TypeAdapters.CALENDAR_FACTORY); + factories.add(TimeTypeAdapter.FACTORY); + factories.add(SqlDateTypeAdapter.FACTORY); + factories.add(TypeAdapters.TIMESTAMP_FACTORY); + factories.add(ArrayTypeAdapter.FACTORY); + factories.add(TypeAdapters.ENUM_FACTORY); + factories.add(TypeAdapters.CLASS_FACTORY); + factories.add(new CollectionTypeAdapterFactory(this.constructorConstructor)); + factories.add(new MapTypeAdapterFactory(this.constructorConstructor, complexMapKeySerialization)); + factories.add(new ReflectiveTypeAdapterFactory(this.constructorConstructor, fieldNamingPolicy, excluder)); + this.factories = Collections.unmodifiableList(factories); + } + + private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.DOUBLE; + } + return new TypeAdapter(){ + + @Override + public Double read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return in.nextDouble(); + } + + @Override + public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + double doubleValue = value.doubleValue(); + Gson.this.checkValidFloatingPoint(doubleValue); + out.value(value); + } + }; + } + + private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.FLOAT; + } + return new TypeAdapter(){ + + @Override + public Float read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return Float.valueOf((float)in.nextDouble()); + } + + @Override + public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + float floatValue = value.floatValue(); + Gson.this.checkValidFloatingPoint(floatValue); + out.value(value); + } + }; + } + + private void checkValidFloatingPoint(double value) { + if (Double.isNaN(value) || Double.isInfinite(value)) { + throw new IllegalArgumentException(value + " is not a valid double value as per JSON specification. To override this" + " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method."); + } + } + + private TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) { + if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) { + return TypeAdapters.LONG; + } + return new TypeAdapter(){ + + @Override + public Number read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return in.nextLong(); + } + + @Override + public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.value(value.toString()); + } + }; + } + + public TypeAdapter getAdapter(TypeToken type) { + FutureTypeAdapter ongoingCall; + TypeAdapter cached = this.typeTokenCache.get(type); + if (cached != null) { + return cached; + } + Map, FutureTypeAdapter> threadCalls = this.calls.get(); + boolean requiresThreadLocalCleanup = false; + if (threadCalls == null) { + threadCalls = new HashMap(); + this.calls.set(threadCalls); + requiresThreadLocalCleanup = true; + } + if ((ongoingCall = threadCalls.get(type)) != null) { + return ongoingCall; + } + try { + FutureTypeAdapter call = new FutureTypeAdapter(); + threadCalls.put(type, call); + for (TypeAdapterFactory factory : this.factories) { + TypeAdapter candidate = factory.create(this, type); + if (candidate == null) continue; + call.setDelegate(candidate); + this.typeTokenCache.put(type, candidate); + TypeAdapter typeAdapter = candidate; + return typeAdapter; + } + throw new IllegalArgumentException("GSON cannot handle " + type); + } + finally { + threadCalls.remove(type); + if (requiresThreadLocalCleanup) { + this.calls.remove(); + } + } + } + + public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken type) { + boolean skipPastFound = false; + for (TypeAdapterFactory factory : this.factories) { + if (!skipPastFound) { + if (factory != skipPast) continue; + skipPastFound = true; + continue; + } + TypeAdapter candidate = factory.create(this, type); + if (candidate == null) continue; + return candidate; + } + throw new IllegalArgumentException("GSON cannot serialize " + type); + } + + public TypeAdapter getAdapter(Class type) { + return this.getAdapter(TypeToken.get(type)); + } + + public JsonElement toJsonTree(Object src) { + if (src == null) { + return JsonNull.INSTANCE; + } + return this.toJsonTree(src, src.getClass()); + } + + public JsonElement toJsonTree(Object src, Type typeOfSrc) { + JsonTreeWriter writer = new JsonTreeWriter(); + this.toJson(src, typeOfSrc, writer); + return writer.get(); + } + + public String toJson(Object src) { + if (src == null) { + return this.toJson(JsonNull.INSTANCE); + } + return this.toJson(src, src.getClass()); + } + + public String toJson(Object src, Type typeOfSrc) { + StringWriter writer = new StringWriter(); + this.toJson(src, typeOfSrc, writer); + return writer.toString(); + } + + public void toJson(Object src, Appendable writer) throws JsonIOException { + if (src != null) { + this.toJson(src, src.getClass(), writer); + } else { + this.toJson((JsonElement)JsonNull.INSTANCE, writer); + } + } + + public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException { + try { + JsonWriter jsonWriter = this.newJsonWriter(Streams.writerForAppendable(writer)); + this.toJson(src, typeOfSrc, jsonWriter); + } + catch (IOException e) { + throw new JsonIOException(e); + } + } + + public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { + TypeAdapter adapter = this.getAdapter(TypeToken.get(typeOfSrc)); + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(this.htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(this.serializeNulls); + try { + adapter.write(writer, src); + } + catch (IOException e) { + throw new JsonIOException(e); + } + finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + public String toJson(JsonElement jsonElement) { + StringWriter writer = new StringWriter(); + this.toJson(jsonElement, (Appendable)writer); + return writer.toString(); + } + + public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException { + try { + JsonWriter jsonWriter = this.newJsonWriter(Streams.writerForAppendable(writer)); + this.toJson(jsonElement, jsonWriter); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + private JsonWriter newJsonWriter(Writer writer) throws IOException { + if (this.generateNonExecutableJson) { + writer.write(JSON_NON_EXECUTABLE_PREFIX); + } + JsonWriter jsonWriter = new JsonWriter(writer); + if (this.prettyPrinting) { + jsonWriter.setIndent(" "); + } + jsonWriter.setSerializeNulls(this.serializeNulls); + return jsonWriter; + } + + public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException { + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(this.htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(this.serializeNulls); + try { + Streams.write(jsonElement, writer); + } + catch (IOException e) { + throw new JsonIOException(e); + } + finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + public T fromJson(String json, Class classOfT) throws JsonSyntaxException { + T object = this.fromJson(json, (Type)classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { + if (json == null) { + return null; + } + StringReader reader = new StringReader(json); + T target = this.fromJson((Reader)reader, typeOfT); + return target; + } + + public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { + JsonReader jsonReader = new JsonReader(json); + T object = this.fromJson(jsonReader, classOfT); + Gson.assertFullConsumption(object, jsonReader); + return Primitives.wrap(classOfT).cast(object); + } + + public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { + JsonReader jsonReader = new JsonReader(json); + T object = this.fromJson(jsonReader, typeOfT); + Gson.assertFullConsumption(object, jsonReader); + return object; + } + + private static void assertFullConsumption(Object obj, JsonReader reader) { + try { + if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { + throw new JsonIOException("JSON document was not fully consumed."); + } + } + catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonIOException(e); + } + } + + public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { + boolean isEmpty = true; + boolean oldLenient = reader.isLenient(); + reader.setLenient(true); + try { + Object object; + reader.peek(); + isEmpty = false; + TypeToken typeToken = TypeToken.get(typeOfT); + TypeAdapter typeAdapter = this.getAdapter(typeToken); + Object obj = object = typeAdapter.read(reader); + return (T)obj; + } + catch (EOFException e) { + if (isEmpty) { + T t = null; + return t; + } + throw new JsonSyntaxException(e); + } + catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonSyntaxException(e); + } + finally { + reader.setLenient(oldLenient); + } + } + + public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { + T object = this.fromJson(json, (Type)classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { + if (json == null) { + return null; + } + return this.fromJson(new JsonTreeReader(json), typeOfT); + } + + public String toString() { + return "{serializeNulls:" + this.serializeNulls + "factories:" + this.factories + ",instanceCreators:" + this.constructorConstructor + "}"; + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + static class FutureTypeAdapter + extends TypeAdapter { + private TypeAdapter delegate; + + FutureTypeAdapter() { + } + + public void setDelegate(TypeAdapter typeAdapter) { + if (this.delegate != null) { + throw new AssertionError(); + } + this.delegate = typeAdapter; + } + + @Override + public T read(JsonReader in) throws IOException { + if (this.delegate == null) { + throw new IllegalStateException(); + } + return this.delegate.read(in); + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (this.delegate == null) { + throw new IllegalStateException(); + } + this.delegate.write(out, value); + } + } +} diff --git a/src/com/google/gson/GsonBuilder.java b/src/com/google/gson/GsonBuilder.java new file mode 100644 index 0000000..ac1f54e --- /dev/null +++ b/src/com/google/gson/GsonBuilder.java @@ -0,0 +1,204 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.DefaultDateTypeAdapter; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldNamingPolicy; +import com.google.gson.FieldNamingStrategy; +import com.google.gson.Gson; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializer; +import com.google.gson.LongSerializationPolicy; +import com.google.gson.TreeTypeAdapter; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Preconditions; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.sql.Date; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class GsonBuilder { + private Excluder excluder = Excluder.DEFAULT; + private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; + private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY; + private final Map> instanceCreators = new HashMap(); + private final List factories = new ArrayList(); + private final List hierarchyFactories = new ArrayList(); + private boolean serializeNulls; + private String datePattern; + private int dateStyle = 2; + private int timeStyle = 2; + private boolean complexMapKeySerialization; + private boolean serializeSpecialFloatingPointValues; + private boolean escapeHtmlChars = true; + private boolean prettyPrinting; + private boolean generateNonExecutableJson; + + public GsonBuilder setVersion(double ignoreVersionsAfter) { + this.excluder = this.excluder.withVersion(ignoreVersionsAfter); + return this; + } + + public GsonBuilder excludeFieldsWithModifiers(int ... modifiers) { + this.excluder = this.excluder.withModifiers(modifiers); + return this; + } + + public GsonBuilder generateNonExecutableJson() { + this.generateNonExecutableJson = true; + return this; + } + + public GsonBuilder excludeFieldsWithoutExposeAnnotation() { + this.excluder = this.excluder.excludeFieldsWithoutExposeAnnotation(); + return this; + } + + public GsonBuilder serializeNulls() { + this.serializeNulls = true; + return this; + } + + public GsonBuilder enableComplexMapKeySerialization() { + this.complexMapKeySerialization = true; + return this; + } + + public GsonBuilder disableInnerClassSerialization() { + this.excluder = this.excluder.disableInnerClassSerialization(); + return this; + } + + public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) { + this.longSerializationPolicy = serializationPolicy; + return this; + } + + public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) { + this.fieldNamingPolicy = namingConvention; + return this; + } + + public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) { + this.fieldNamingPolicy = fieldNamingStrategy; + return this; + } + + public GsonBuilder setExclusionStrategies(ExclusionStrategy ... strategies) { + for (ExclusionStrategy strategy : strategies) { + this.excluder = this.excluder.withExclusionStrategy(strategy, true, true); + } + return this; + } + + public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) { + this.excluder = this.excluder.withExclusionStrategy(strategy, true, false); + return this; + } + + public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) { + this.excluder = this.excluder.withExclusionStrategy(strategy, false, true); + return this; + } + + public GsonBuilder setPrettyPrinting() { + this.prettyPrinting = true; + return this; + } + + public GsonBuilder disableHtmlEscaping() { + this.escapeHtmlChars = false; + return this; + } + + public GsonBuilder setDateFormat(String pattern) { + this.datePattern = pattern; + return this; + } + + public GsonBuilder setDateFormat(int style) { + this.dateStyle = style; + this.datePattern = null; + return this; + } + + public GsonBuilder setDateFormat(int dateStyle, int timeStyle) { + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + this.datePattern = null; + return this; + } + + public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { + $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer || typeAdapter instanceof JsonDeserializer || typeAdapter instanceof InstanceCreator || typeAdapter instanceof TypeAdapter); + if (typeAdapter instanceof InstanceCreator) { + this.instanceCreators.put(type, (InstanceCreator)typeAdapter); + } + if (typeAdapter instanceof JsonSerializer || typeAdapter instanceof JsonDeserializer) { + TypeToken typeToken = TypeToken.get(type); + this.factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter)); + } + if (typeAdapter instanceof TypeAdapter) { + this.factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter)); + } + return this; + } + + public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) { + this.factories.add(factory); + return this; + } + + public GsonBuilder registerTypeHierarchyAdapter(Class baseType, Object typeAdapter) { + $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer || typeAdapter instanceof JsonDeserializer || typeAdapter instanceof TypeAdapter); + if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) { + this.hierarchyFactories.add(0, TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); + } + if (typeAdapter instanceof TypeAdapter) { + this.factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter)); + } + return this; + } + + public GsonBuilder serializeSpecialFloatingPointValues() { + this.serializeSpecialFloatingPointValues = true; + return this; + } + + public Gson create() { + ArrayList factories = new ArrayList(); + factories.addAll(this.factories); + Collections.reverse(factories); + factories.addAll(this.hierarchyFactories); + this.addTypeAdaptersForDate(this.datePattern, this.dateStyle, this.timeStyle, factories); + return new Gson(this.excluder, this.fieldNamingPolicy, this.instanceCreators, this.serializeNulls, this.complexMapKeySerialization, this.generateNonExecutableJson, this.escapeHtmlChars, this.prettyPrinting, this.serializeSpecialFloatingPointValues, this.longSerializationPolicy, factories); + } + + private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, List factories) { + DefaultDateTypeAdapter dateTypeAdapter; + if (datePattern != null && !"".equals(datePattern.trim())) { + dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); + } else if (dateStyle != 2 && timeStyle != 2) { + dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); + } else { + return; + } + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.util.Date.class), dateTypeAdapter)); + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter)); + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter)); + } +} diff --git a/src/com/google/gson/InstanceCreator.java b/src/com/google/gson/InstanceCreator.java new file mode 100644 index 0000000..493d36e --- /dev/null +++ b/src/com/google/gson/InstanceCreator.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import java.lang.reflect.Type; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface InstanceCreator { + public T createInstance(Type var1); +} diff --git a/src/com/google/gson/JsonArray.java b/src/com/google/gson/JsonArray.java new file mode 100644 index 0000000..6a8c45a --- /dev/null +++ b/src/com/google/gson/JsonArray.java @@ -0,0 +1,158 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class JsonArray +extends JsonElement +implements Iterable { + private final List elements = new ArrayList(); + + @Override + JsonArray deepCopy() { + JsonArray result = new JsonArray(); + for (JsonElement element : this.elements) { + result.add(element.deepCopy()); + } + return result; + } + + public void add(JsonElement element) { + if (element == null) { + element = JsonNull.INSTANCE; + } + this.elements.add(element); + } + + public void addAll(JsonArray array) { + this.elements.addAll(array.elements); + } + + public int size() { + return this.elements.size(); + } + + @Override + public Iterator iterator() { + return this.elements.iterator(); + } + + public JsonElement get(int i) { + return this.elements.get(i); + } + + @Override + public Number getAsNumber() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsNumber(); + } + throw new IllegalStateException(); + } + + @Override + public String getAsString() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsString(); + } + throw new IllegalStateException(); + } + + @Override + public double getAsDouble() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsDouble(); + } + throw new IllegalStateException(); + } + + @Override + public BigDecimal getAsBigDecimal() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsBigDecimal(); + } + throw new IllegalStateException(); + } + + @Override + public BigInteger getAsBigInteger() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsBigInteger(); + } + throw new IllegalStateException(); + } + + @Override + public float getAsFloat() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsFloat(); + } + throw new IllegalStateException(); + } + + @Override + public long getAsLong() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsLong(); + } + throw new IllegalStateException(); + } + + @Override + public int getAsInt() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsInt(); + } + throw new IllegalStateException(); + } + + @Override + public byte getAsByte() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsByte(); + } + throw new IllegalStateException(); + } + + @Override + public char getAsCharacter() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsCharacter(); + } + throw new IllegalStateException(); + } + + @Override + public short getAsShort() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsShort(); + } + throw new IllegalStateException(); + } + + @Override + public boolean getAsBoolean() { + if (this.elements.size() == 1) { + return this.elements.get(0).getAsBoolean(); + } + throw new IllegalStateException(); + } + + public boolean equals(Object o) { + return o == this || o instanceof JsonArray && ((JsonArray)o).elements.equals(this.elements); + } + + public int hashCode() { + return this.elements.hashCode(); + } +} diff --git a/src/com/google/gson/JsonDeserializationContext.java b/src/com/google/gson/JsonDeserializationContext.java new file mode 100644 index 0000000..37f3269 --- /dev/null +++ b/src/com/google/gson/JsonDeserializationContext.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import java.lang.reflect.Type; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface JsonDeserializationContext { + public T deserialize(JsonElement var1, Type var2) throws JsonParseException; +} diff --git a/src/com/google/gson/JsonDeserializer.java b/src/com/google/gson/JsonDeserializer.java new file mode 100644 index 0000000..3900279 --- /dev/null +++ b/src/com/google/gson/JsonDeserializer.java @@ -0,0 +1,16 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import java.lang.reflect.Type; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface JsonDeserializer { + public T deserialize(JsonElement var1, Type var2, JsonDeserializationContext var3) throws JsonParseException; +} diff --git a/src/com/google/gson/JsonElement.java b/src/com/google/gson/JsonElement.java new file mode 100644 index 0000000..dfda1f4 --- /dev/null +++ b/src/com/google/gson/JsonElement.java @@ -0,0 +1,128 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonArray; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; + +public abstract class JsonElement { + abstract JsonElement deepCopy(); + + public boolean isJsonArray() { + return this instanceof JsonArray; + } + + public boolean isJsonObject() { + return this instanceof JsonObject; + } + + public boolean isJsonPrimitive() { + return this instanceof JsonPrimitive; + } + + public boolean isJsonNull() { + return this instanceof JsonNull; + } + + public JsonObject getAsJsonObject() { + if (this.isJsonObject()) { + return (JsonObject)this; + } + throw new IllegalStateException("Not a JSON Object: " + this); + } + + public JsonArray getAsJsonArray() { + if (this.isJsonArray()) { + return (JsonArray)this; + } + throw new IllegalStateException("This is not a JSON Array."); + } + + public JsonPrimitive getAsJsonPrimitive() { + if (this.isJsonPrimitive()) { + return (JsonPrimitive)this; + } + throw new IllegalStateException("This is not a JSON Primitive."); + } + + public JsonNull getAsJsonNull() { + if (this.isJsonNull()) { + return (JsonNull)this; + } + throw new IllegalStateException("This is not a JSON Null."); + } + + public boolean getAsBoolean() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + Boolean getAsBooleanWrapper() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public Number getAsNumber() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public String getAsString() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public double getAsDouble() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public float getAsFloat() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public long getAsLong() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public int getAsInt() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public byte getAsByte() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public char getAsCharacter() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public BigDecimal getAsBigDecimal() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public BigInteger getAsBigInteger() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public short getAsShort() { + throw new UnsupportedOperationException(this.getClass().getSimpleName()); + } + + public String toString() { + try { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setLenient(true); + Streams.write(this, jsonWriter); + return stringWriter.toString(); + } + catch (IOException e) { + throw new AssertionError((Object)e); + } + } +} diff --git a/src/com/google/gson/JsonIOException.java b/src/com/google/gson/JsonIOException.java new file mode 100644 index 0000000..6bf264b --- /dev/null +++ b/src/com/google/gson/JsonIOException.java @@ -0,0 +1,23 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonParseException; + +public final class JsonIOException +extends JsonParseException { + private static final long serialVersionUID = 1L; + + public JsonIOException(String msg) { + super(msg); + } + + public JsonIOException(String msg, Throwable cause) { + super(msg, cause); + } + + public JsonIOException(Throwable cause) { + super(cause); + } +} diff --git a/src/com/google/gson/JsonNull.java b/src/com/google/gson/JsonNull.java new file mode 100644 index 0000000..01c8851 --- /dev/null +++ b/src/com/google/gson/JsonNull.java @@ -0,0 +1,27 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; + +public final class JsonNull +extends JsonElement { + public static final JsonNull INSTANCE = new JsonNull(); + + @Deprecated + public JsonNull() { + } + + JsonNull deepCopy() { + return INSTANCE; + } + + public int hashCode() { + return JsonNull.class.hashCode(); + } + + public boolean equals(Object other) { + return this == other || other instanceof JsonNull; + } +} diff --git a/src/com/google/gson/JsonObject.java b/src/com/google/gson/JsonObject.java new file mode 100644 index 0000000..641ca24 --- /dev/null +++ b/src/com/google/gson/JsonObject.java @@ -0,0 +1,92 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonPrimitive; +import com.google.gson.internal.LinkedTreeMap; +import java.util.Map; +import java.util.Set; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class JsonObject +extends JsonElement { + private final LinkedTreeMap members = new LinkedTreeMap(); + + @Override + JsonObject deepCopy() { + JsonObject result = new JsonObject(); + for (Map.Entry entry : this.members.entrySet()) { + result.add(entry.getKey(), entry.getValue().deepCopy()); + } + return result; + } + + public void add(String property, JsonElement value) { + if (value == null) { + value = JsonNull.INSTANCE; + } + this.members.put(property, value); + } + + public JsonElement remove(String property) { + return this.members.remove(property); + } + + public void addProperty(String property, String value) { + this.add(property, this.createJsonElement(value)); + } + + public void addProperty(String property, Number value) { + this.add(property, this.createJsonElement(value)); + } + + public void addProperty(String property, Boolean value) { + this.add(property, this.createJsonElement(value)); + } + + public void addProperty(String property, Character value) { + this.add(property, this.createJsonElement(value)); + } + + private JsonElement createJsonElement(Object value) { + return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value); + } + + public Set> entrySet() { + return this.members.entrySet(); + } + + public boolean has(String memberName) { + return this.members.containsKey(memberName); + } + + public JsonElement get(String memberName) { + return this.members.get(memberName); + } + + public JsonPrimitive getAsJsonPrimitive(String memberName) { + return (JsonPrimitive)this.members.get(memberName); + } + + public JsonArray getAsJsonArray(String memberName) { + return (JsonArray)this.members.get(memberName); + } + + public JsonObject getAsJsonObject(String memberName) { + return (JsonObject)this.members.get(memberName); + } + + public boolean equals(Object o) { + return o == this || o instanceof JsonObject && ((JsonObject)o).members.equals(this.members); + } + + public int hashCode() { + return this.members.hashCode(); + } +} diff --git a/src/com/google/gson/JsonParseException.java b/src/com/google/gson/JsonParseException.java new file mode 100644 index 0000000..4a3b8c4 --- /dev/null +++ b/src/com/google/gson/JsonParseException.java @@ -0,0 +1,21 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +public class JsonParseException +extends RuntimeException { + static final long serialVersionUID = -4086729973971783390L; + + public JsonParseException(String msg) { + super(msg); + } + + public JsonParseException(String msg, Throwable cause) { + super(msg, cause); + } + + public JsonParseException(Throwable cause) { + super(cause); + } +} diff --git a/src/com/google/gson/JsonParser.java b/src/com/google/gson/JsonParser.java new file mode 100644 index 0000000..7988ab6 --- /dev/null +++ b/src/com/google/gson/JsonParser.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.MalformedJsonException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +public final class JsonParser { + public JsonElement parse(String json) throws JsonSyntaxException { + return this.parse(new StringReader(json)); + } + + public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException { + try { + JsonReader jsonReader = new JsonReader(json); + JsonElement element = this.parse(jsonReader); + if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) { + throw new JsonSyntaxException("Did not consume the entire document."); + } + return element; + } + catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonIOException(e); + } + catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException { + boolean lenient = json.isLenient(); + json.setLenient(true); + try { + JsonElement jsonElement = Streams.parse(json); + return jsonElement; + } + catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } + catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } + finally { + json.setLenient(lenient); + } + } +} diff --git a/src/com/google/gson/JsonPrimitive.java b/src/com/google/gson/JsonPrimitive.java new file mode 100644 index 0000000..522ba8c --- /dev/null +++ b/src/com/google/gson/JsonPrimitive.java @@ -0,0 +1,180 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.internal.$Gson$Preconditions; +import com.google.gson.internal.LazilyParsedNumber; +import java.math.BigDecimal; +import java.math.BigInteger; + +public final class JsonPrimitive +extends JsonElement { + private static final Class[] PRIMITIVE_TYPES = new Class[]{Integer.TYPE, Long.TYPE, Short.TYPE, Float.TYPE, Double.TYPE, Byte.TYPE, Boolean.TYPE, Character.TYPE, Integer.class, Long.class, Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class}; + private Object value; + + public JsonPrimitive(Boolean bool) { + this.setValue(bool); + } + + public JsonPrimitive(Number number) { + this.setValue(number); + } + + public JsonPrimitive(String string) { + this.setValue(string); + } + + public JsonPrimitive(Character c) { + this.setValue(c); + } + + JsonPrimitive(Object primitive) { + this.setValue(primitive); + } + + JsonPrimitive deepCopy() { + return this; + } + + void setValue(Object primitive) { + if (primitive instanceof Character) { + char c = ((Character)primitive).charValue(); + this.value = String.valueOf(c); + } else { + $Gson$Preconditions.checkArgument(primitive instanceof Number || JsonPrimitive.isPrimitiveOrString(primitive)); + this.value = primitive; + } + } + + public boolean isBoolean() { + return this.value instanceof Boolean; + } + + Boolean getAsBooleanWrapper() { + return (Boolean)this.value; + } + + public boolean getAsBoolean() { + if (this.isBoolean()) { + return this.getAsBooleanWrapper(); + } + return Boolean.parseBoolean(this.getAsString()); + } + + public boolean isNumber() { + return this.value instanceof Number; + } + + public Number getAsNumber() { + return this.value instanceof String ? new LazilyParsedNumber((String)this.value) : (Number)this.value; + } + + public boolean isString() { + return this.value instanceof String; + } + + public String getAsString() { + if (this.isNumber()) { + return this.getAsNumber().toString(); + } + if (this.isBoolean()) { + return this.getAsBooleanWrapper().toString(); + } + return (String)this.value; + } + + public double getAsDouble() { + return this.isNumber() ? this.getAsNumber().doubleValue() : Double.parseDouble(this.getAsString()); + } + + public BigDecimal getAsBigDecimal() { + return this.value instanceof BigDecimal ? (BigDecimal)this.value : new BigDecimal(this.value.toString()); + } + + public BigInteger getAsBigInteger() { + return this.value instanceof BigInteger ? (BigInteger)this.value : new BigInteger(this.value.toString()); + } + + public float getAsFloat() { + return this.isNumber() ? this.getAsNumber().floatValue() : Float.parseFloat(this.getAsString()); + } + + public long getAsLong() { + return this.isNumber() ? this.getAsNumber().longValue() : Long.parseLong(this.getAsString()); + } + + public short getAsShort() { + return this.isNumber() ? this.getAsNumber().shortValue() : Short.parseShort(this.getAsString()); + } + + public int getAsInt() { + return this.isNumber() ? this.getAsNumber().intValue() : Integer.parseInt(this.getAsString()); + } + + public byte getAsByte() { + return this.isNumber() ? this.getAsNumber().byteValue() : Byte.parseByte(this.getAsString()); + } + + public char getAsCharacter() { + return this.getAsString().charAt(0); + } + + private static boolean isPrimitiveOrString(Object target) { + if (target instanceof String) { + return true; + } + Class classOfPrimitive = target.getClass(); + for (Class standardPrimitive : PRIMITIVE_TYPES) { + if (!standardPrimitive.isAssignableFrom(classOfPrimitive)) continue; + return true; + } + return false; + } + + public int hashCode() { + if (this.value == null) { + return 31; + } + if (JsonPrimitive.isIntegral(this)) { + long value = this.getAsNumber().longValue(); + return (int)(value ^ value >>> 32); + } + if (this.value instanceof Number) { + long value = Double.doubleToLongBits(this.getAsNumber().doubleValue()); + return (int)(value ^ value >>> 32); + } + return this.value.hashCode(); + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || this.getClass() != obj.getClass()) { + return false; + } + JsonPrimitive other = (JsonPrimitive)obj; + if (this.value == null) { + return other.value == null; + } + if (JsonPrimitive.isIntegral(this) && JsonPrimitive.isIntegral(other)) { + return this.getAsNumber().longValue() == other.getAsNumber().longValue(); + } + if (this.value instanceof Number && other.value instanceof Number) { + double b; + double a = this.getAsNumber().doubleValue(); + return a == (b = other.getAsNumber().doubleValue()) || Double.isNaN(a) && Double.isNaN(b); + } + return this.value.equals(other.value); + } + + private static boolean isIntegral(JsonPrimitive primitive) { + if (primitive.value instanceof Number) { + Number number = (Number)primitive.value; + return number instanceof BigInteger || number instanceof Long || number instanceof Integer || number instanceof Short || number instanceof Byte; + } + return false; + } +} diff --git a/src/com/google/gson/JsonSerializationContext.java b/src/com/google/gson/JsonSerializationContext.java new file mode 100644 index 0000000..3be2d84 --- /dev/null +++ b/src/com/google/gson/JsonSerializationContext.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import java.lang.reflect.Type; + +public interface JsonSerializationContext { + public JsonElement serialize(Object var1); + + public JsonElement serialize(Object var1, Type var2); +} diff --git a/src/com/google/gson/JsonSerializer.java b/src/com/google/gson/JsonSerializer.java new file mode 100644 index 0000000..2e9dfcd --- /dev/null +++ b/src/com/google/gson/JsonSerializer.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonSerializationContext; +import java.lang.reflect.Type; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface JsonSerializer { + public JsonElement serialize(T var1, Type var2, JsonSerializationContext var3); +} diff --git a/src/com/google/gson/JsonStreamParser.java b/src/com/google/gson/JsonStreamParser.java new file mode 100644 index 0000000..c1a5593 --- /dev/null +++ b/src/com/google/gson/JsonStreamParser.java @@ -0,0 +1,78 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class JsonStreamParser +implements Iterator { + private final JsonReader parser; + private final Object lock; + + public JsonStreamParser(String json) { + this(new StringReader(json)); + } + + public JsonStreamParser(Reader reader) { + this.parser = new JsonReader(reader); + this.parser.setLenient(true); + this.lock = new Object(); + } + + @Override + public JsonElement next() throws JsonParseException { + if (!this.hasNext()) { + throw new NoSuchElementException(); + } + try { + return Streams.parse(this.parser); + } + catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } + catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } + catch (JsonParseException e) { + throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e; + } + } + + @Override + public boolean hasNext() { + Object object = this.lock; + synchronized (object) { + try { + return this.parser.peek() != JsonToken.END_DOCUMENT; + } + catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonIOException(e); + } + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/com/google/gson/JsonSyntaxException.java b/src/com/google/gson/JsonSyntaxException.java new file mode 100644 index 0000000..dda0719 --- /dev/null +++ b/src/com/google/gson/JsonSyntaxException.java @@ -0,0 +1,23 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonParseException; + +public final class JsonSyntaxException +extends JsonParseException { + private static final long serialVersionUID = 1L; + + public JsonSyntaxException(String msg) { + super(msg); + } + + public JsonSyntaxException(String msg, Throwable cause) { + super(msg, cause); + } + + public JsonSyntaxException(Throwable cause) { + super(cause); + } +} diff --git a/src/com/google/gson/LongSerializationPolicy.java b/src/com/google/gson/LongSerializationPolicy.java new file mode 100644 index 0000000..87eecd7 --- /dev/null +++ b/src/com/google/gson/LongSerializationPolicy.java @@ -0,0 +1,29 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public enum LongSerializationPolicy { + DEFAULT{ + + public JsonElement serialize(Long value) { + return new JsonPrimitive(value); + } + } + , + STRING{ + + public JsonElement serialize(Long value) { + return new JsonPrimitive(String.valueOf(value)); + } + }; + + + public abstract JsonElement serialize(Long var1); +} diff --git a/src/com/google/gson/TreeTypeAdapter.java b/src/com/google/gson/TreeTypeAdapter.java new file mode 100644 index 0000000..6ce3241 --- /dev/null +++ b/src/com/google/gson/TreeTypeAdapter.java @@ -0,0 +1,109 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.Gson; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonSerializer; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Preconditions; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +final class TreeTypeAdapter +extends TypeAdapter { + private final JsonSerializer serializer; + private final JsonDeserializer deserializer; + private final Gson gson; + private final TypeToken typeToken; + private final TypeAdapterFactory skipPast; + private TypeAdapter delegate; + + private TreeTypeAdapter(JsonSerializer serializer, JsonDeserializer deserializer, Gson gson, TypeToken typeToken, TypeAdapterFactory skipPast) { + this.serializer = serializer; + this.deserializer = deserializer; + this.gson = gson; + this.typeToken = typeToken; + this.skipPast = skipPast; + } + + @Override + public T read(JsonReader in) throws IOException { + if (this.deserializer == null) { + return this.delegate().read(in); + } + JsonElement value = Streams.parse(in); + if (value.isJsonNull()) { + return null; + } + return this.deserializer.deserialize(value, this.typeToken.getType(), this.gson.deserializationContext); + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (this.serializer == null) { + this.delegate().write(out, value); + return; + } + if (value == null) { + out.nullValue(); + return; + } + JsonElement tree = this.serializer.serialize(value, this.typeToken.getType(), this.gson.serializationContext); + Streams.write(tree, out); + } + + private TypeAdapter delegate() { + TypeAdapter d = this.delegate; + return d != null ? d : (this.delegate = this.gson.getDelegateAdapter(this.skipPast, this.typeToken)); + } + + public static TypeAdapterFactory newFactory(TypeToken exactType, Object typeAdapter) { + return new SingleTypeFactory(typeAdapter, exactType, false, null); + } + + public static TypeAdapterFactory newFactoryWithMatchRawType(TypeToken exactType, Object typeAdapter) { + boolean matchRawType = exactType.getType() == exactType.getRawType(); + return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null); + } + + public static TypeAdapterFactory newTypeHierarchyFactory(Class hierarchyType, Object typeAdapter) { + return new SingleTypeFactory(typeAdapter, null, false, hierarchyType); + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + private static class SingleTypeFactory + implements TypeAdapterFactory { + private final TypeToken exactType; + private final boolean matchRawType; + private final Class hierarchyType; + private final JsonSerializer serializer; + private final JsonDeserializer deserializer; + + private SingleTypeFactory(Object typeAdapter, TypeToken exactType, boolean matchRawType, Class hierarchyType) { + this.serializer = typeAdapter instanceof JsonSerializer ? (JsonSerializer)typeAdapter : null; + this.deserializer = typeAdapter instanceof JsonDeserializer ? (JsonDeserializer)typeAdapter : null; + $Gson$Preconditions.checkArgument(this.serializer != null || this.deserializer != null); + this.exactType = exactType; + this.matchRawType = matchRawType; + this.hierarchyType = hierarchyType; + } + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + boolean matches = this.exactType != null ? this.exactType.equals(type) || this.matchRawType && this.exactType.getType() == type.getRawType() : this.hierarchyType.isAssignableFrom(type.getRawType()); + return matches ? new TreeTypeAdapter(this.serializer, this.deserializer, gson, type, this) : null; + } + } +} diff --git a/src/com/google/gson/TypeAdapter.java b/src/com/google/gson/TypeAdapter.java new file mode 100644 index 0000000..cc516cf --- /dev/null +++ b/src/com/google/gson/TypeAdapter.java @@ -0,0 +1,90 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.internal.bind.JsonTreeReader; +import com.google.gson.internal.bind.JsonTreeWriter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public abstract class TypeAdapter { + public abstract void write(JsonWriter var1, T var2) throws IOException; + + public final void toJson(Writer out, T value) throws IOException { + JsonWriter writer = new JsonWriter(out); + this.write(writer, value); + } + + public final TypeAdapter nullSafe() { + return new TypeAdapter(){ + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + TypeAdapter.this.write(out, value); + } + } + + @Override + public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return TypeAdapter.this.read(reader); + } + }; + } + + public final String toJson(T value) throws IOException { + StringWriter stringWriter = new StringWriter(); + this.toJson(stringWriter, value); + return stringWriter.toString(); + } + + public final JsonElement toJsonTree(T value) { + try { + JsonTreeWriter jsonWriter = new JsonTreeWriter(); + this.write(jsonWriter, value); + return jsonWriter.get(); + } + catch (IOException e) { + throw new JsonIOException(e); + } + } + + public abstract T read(JsonReader var1) throws IOException; + + public final T fromJson(Reader in) throws IOException { + JsonReader reader = new JsonReader(in); + return this.read(reader); + } + + public final T fromJson(String json) throws IOException { + return this.fromJson(new StringReader(json)); + } + + public final T fromJsonTree(JsonElement jsonTree) { + try { + JsonTreeReader jsonReader = new JsonTreeReader(jsonTree); + return this.read(jsonReader); + } + catch (IOException e) { + throw new JsonIOException(e); + } + } +} diff --git a/src/com/google/gson/TypeAdapterFactory.java b/src/com/google/gson/TypeAdapterFactory.java new file mode 100644 index 0000000..2d8bec8 --- /dev/null +++ b/src/com/google/gson/TypeAdapterFactory.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface TypeAdapterFactory { + public TypeAdapter create(Gson var1, TypeToken var2); +} diff --git a/src/com/google/gson/annotations/Expose.java b/src/com/google/gson/annotations/Expose.java new file mode 100644 index 0000000..6ff01ec --- /dev/null +++ b/src/com/google/gson/annotations/Expose.java @@ -0,0 +1,17 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.FIELD}) +public @interface Expose { + public boolean serialize() default true; + + public boolean deserialize() default true; +} diff --git a/src/com/google/gson/annotations/SerializedName.java b/src/com/google/gson/annotations/SerializedName.java new file mode 100644 index 0000000..e86c478 --- /dev/null +++ b/src/com/google/gson/annotations/SerializedName.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.FIELD}) +public @interface SerializedName { + public String value(); +} diff --git a/src/com/google/gson/annotations/Since.java b/src/com/google/gson/annotations/Since.java new file mode 100644 index 0000000..978afcb --- /dev/null +++ b/src/com/google/gson/annotations/Since.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.FIELD, ElementType.TYPE}) +public @interface Since { + public double value(); +} diff --git a/src/com/google/gson/annotations/Until.java b/src/com/google/gson/annotations/Until.java new file mode 100644 index 0000000..426cf2c --- /dev/null +++ b/src/com/google/gson/annotations/Until.java @@ -0,0 +1,15 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value={ElementType.FIELD, ElementType.TYPE}) +public @interface Until { + public double value(); +} diff --git a/src/com/google/gson/internal/ConstructorConstructor.java b/src/com/google/gson/internal/ConstructorConstructor.java new file mode 100644 index 0000000..2ce7100 --- /dev/null +++ b/src/com/google/gson/internal/ConstructorConstructor.java @@ -0,0 +1,208 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import com.google.gson.InstanceCreator; +import com.google.gson.JsonIOException; +import com.google.gson.internal.LinkedTreeMap; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.UnsafeAllocator; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class ConstructorConstructor { + private final Map> instanceCreators; + + public ConstructorConstructor(Map> instanceCreators) { + this.instanceCreators = instanceCreators; + } + + public ObjectConstructor get(TypeToken typeToken) { + final Type type = typeToken.getType(); + Class rawType = typeToken.getRawType(); + final InstanceCreator typeCreator = this.instanceCreators.get(type); + if (typeCreator != null) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return typeCreator.createInstance(type); + } + }; + } + final InstanceCreator rawTypeCreator = this.instanceCreators.get(rawType); + if (rawTypeCreator != null) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return rawTypeCreator.createInstance(type); + } + }; + } + ObjectConstructor defaultConstructor = this.newDefaultConstructor(rawType); + if (defaultConstructor != null) { + return defaultConstructor; + } + ObjectConstructor defaultImplementation = this.newDefaultImplementationConstructor(type, rawType); + if (defaultImplementation != null) { + return defaultImplementation; + } + return this.newUnsafeAllocator(type, rawType); + } + + private ObjectConstructor newDefaultConstructor(Class rawType) { + try { + final Constructor constructor = rawType.getDeclaredConstructor(new Class[0]); + if (!constructor.isAccessible()) { + constructor.setAccessible(true); + } + return new ObjectConstructor(){ + + @Override + public T construct() { + try { + Object[] args = null; + return constructor.newInstance(args); + } + catch (InstantiationException e) { + throw new RuntimeException("Failed to invoke " + constructor + " with no args", e); + } + catch (InvocationTargetException e) { + throw new RuntimeException("Failed to invoke " + constructor + " with no args", e.getTargetException()); + } + catch (IllegalAccessException e) { + throw new AssertionError((Object)e); + } + } + }; + } + catch (NoSuchMethodException e) { + return null; + } + } + + private ObjectConstructor newDefaultImplementationConstructor(final Type type, Class rawType) { + if (Collection.class.isAssignableFrom(rawType)) { + if (SortedSet.class.isAssignableFrom(rawType)) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return new TreeSet(); + } + }; + } + if (EnumSet.class.isAssignableFrom(rawType)) { + return new ObjectConstructor(){ + + @Override + public T construct() { + if (type instanceof ParameterizedType) { + Type elementType = ((ParameterizedType)type).getActualTypeArguments()[0]; + if (elementType instanceof Class) { + return EnumSet.noneOf((Class)elementType); + } + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + }; + } + if (Set.class.isAssignableFrom(rawType)) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return new LinkedHashSet(); + } + }; + } + if (Queue.class.isAssignableFrom(rawType)) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return new LinkedList(); + } + }; + } + return new ObjectConstructor(){ + + @Override + public T construct() { + return new ArrayList(); + } + }; + } + if (Map.class.isAssignableFrom(rawType)) { + if (SortedMap.class.isAssignableFrom(rawType)) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return new TreeMap(); + } + }; + } + if (type instanceof ParameterizedType && !String.class.isAssignableFrom(TypeToken.get(((ParameterizedType)type).getActualTypeArguments()[0]).getRawType())) { + return new ObjectConstructor(){ + + @Override + public T construct() { + return new LinkedHashMap(); + } + }; + } + return new ObjectConstructor(){ + + @Override + public T construct() { + return new LinkedTreeMap(); + } + }; + } + return null; + } + + private ObjectConstructor newUnsafeAllocator(final Type type, final Class rawType) { + return new ObjectConstructor(){ + private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create(); + + @Override + public T construct() { + try { + Object newInstance = this.unsafeAllocator.newInstance(rawType); + return newInstance; + } + catch (Exception e) { + throw new RuntimeException("Unable to invoke no-args constructor for " + type + ". " + "Register an InstanceCreator with Gson for this type may fix this problem.", e); + } + } + }; + } + + public String toString() { + return this.instanceCreators.toString(); + } +} diff --git a/src/com/google/gson/internal/Excluder.java b/src/com/google/gson/internal/Excluder.java new file mode 100644 index 0000000..3f1bb96 --- /dev/null +++ b/src/com/google/gson/internal/Excluder.java @@ -0,0 +1,198 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.Since; +import com.google.gson.annotations.Until; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class Excluder +implements TypeAdapterFactory, +Cloneable { + private static final double IGNORE_VERSIONS = -1.0; + public static final Excluder DEFAULT = new Excluder(); + private double version = -1.0; + private int modifiers = 136; + private boolean serializeInnerClasses = true; + private boolean requireExpose; + private List serializationStrategies = Collections.emptyList(); + private List deserializationStrategies = Collections.emptyList(); + + protected Excluder clone() { + try { + return (Excluder)super.clone(); + } + catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + + public Excluder withVersion(double ignoreVersionsAfter) { + Excluder result = this.clone(); + result.version = ignoreVersionsAfter; + return result; + } + + public Excluder withModifiers(int ... modifiers) { + Excluder result = this.clone(); + result.modifiers = 0; + for (int modifier : modifiers) { + result.modifiers |= modifier; + } + return result; + } + + public Excluder disableInnerClassSerialization() { + Excluder result = this.clone(); + result.serializeInnerClasses = false; + return result; + } + + public Excluder excludeFieldsWithoutExposeAnnotation() { + Excluder result = this.clone(); + result.requireExpose = true; + return result; + } + + public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy, boolean serialization, boolean deserialization) { + Excluder result = this.clone(); + if (serialization) { + result.serializationStrategies = new ArrayList(this.serializationStrategies); + result.serializationStrategies.add(exclusionStrategy); + } + if (deserialization) { + result.deserializationStrategies = new ArrayList(this.deserializationStrategies); + result.deserializationStrategies.add(exclusionStrategy); + } + return result; + } + + @Override + public TypeAdapter create(final Gson gson, final TypeToken type) { + Class rawType = type.getRawType(); + final boolean skipSerialize = this.excludeClass(rawType, true); + final boolean skipDeserialize = this.excludeClass(rawType, false); + if (!skipSerialize && !skipDeserialize) { + return null; + } + return new TypeAdapter(){ + private TypeAdapter delegate; + + @Override + public T read(JsonReader in) throws IOException { + if (skipDeserialize) { + in.skipValue(); + return null; + } + return this.delegate().read(in); + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (skipSerialize) { + out.nullValue(); + return; + } + this.delegate().write(out, value); + } + + private TypeAdapter delegate() { + TypeAdapter d = this.delegate; + return d != null ? d : (this.delegate = gson.getDelegateAdapter(Excluder.this, type)); + } + }; + } + + public boolean excludeField(Field field, boolean serialize) { + List list; + Expose annotation; + if ((this.modifiers & field.getModifiers()) != 0) { + return true; + } + if (this.version != -1.0 && !this.isValidVersion(field.getAnnotation(Since.class), field.getAnnotation(Until.class))) { + return true; + } + if (field.isSynthetic()) { + return true; + } + if (this.requireExpose && ((annotation = field.getAnnotation(Expose.class)) == null || (serialize ? !annotation.serialize() : !annotation.deserialize()))) { + return true; + } + if (!this.serializeInnerClasses && this.isInnerClass(field.getType())) { + return true; + } + if (this.isAnonymousOrLocal(field.getType())) { + return true; + } + List list2 = list = serialize ? this.serializationStrategies : this.deserializationStrategies; + if (!list.isEmpty()) { + FieldAttributes fieldAttributes = new FieldAttributes(field); + for (ExclusionStrategy exclusionStrategy : list) { + if (!exclusionStrategy.shouldSkipField(fieldAttributes)) continue; + return true; + } + } + return false; + } + + public boolean excludeClass(Class clazz, boolean serialize) { + if (this.version != -1.0 && !this.isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) { + return true; + } + if (!this.serializeInnerClasses && this.isInnerClass(clazz)) { + return true; + } + if (this.isAnonymousOrLocal(clazz)) { + return true; + } + List list = serialize ? this.serializationStrategies : this.deserializationStrategies; + for (ExclusionStrategy exclusionStrategy : list) { + if (!exclusionStrategy.shouldSkipClass(clazz)) continue; + return true; + } + return false; + } + + private boolean isAnonymousOrLocal(Class clazz) { + return !Enum.class.isAssignableFrom(clazz) && (clazz.isAnonymousClass() || clazz.isLocalClass()); + } + + private boolean isInnerClass(Class clazz) { + return clazz.isMemberClass() && !this.isStatic(clazz); + } + + private boolean isStatic(Class clazz) { + return (clazz.getModifiers() & 8) != 0; + } + + private boolean isValidVersion(Since since, Until until) { + return this.isValidSince(since) && this.isValidUntil(until); + } + + private boolean isValidSince(Since annotation) { + double annotationVersion; + return annotation == null || !((annotationVersion = annotation.value()) > this.version); + } + + private boolean isValidUntil(Until annotation) { + double annotationVersion; + return annotation == null || !((annotationVersion = annotation.value()) <= this.version); + } +} diff --git a/src/com/google/gson/internal/JsonReaderInternalAccess.java b/src/com/google/gson/internal/JsonReaderInternalAccess.java new file mode 100644 index 0000000..0ead530 --- /dev/null +++ b/src/com/google/gson/internal/JsonReaderInternalAccess.java @@ -0,0 +1,13 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import com.google.gson.stream.JsonReader; +import java.io.IOException; + +public abstract class JsonReaderInternalAccess { + public static JsonReaderInternalAccess INSTANCE; + + public abstract void promoteNameToValue(JsonReader var1) throws IOException; +} diff --git a/src/com/google/gson/internal/LazilyParsedNumber.java b/src/com/google/gson/internal/LazilyParsedNumber.java new file mode 100644 index 0000000..5c8ce74 --- /dev/null +++ b/src/com/google/gson/internal/LazilyParsedNumber.java @@ -0,0 +1,55 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import java.io.ObjectStreamException; +import java.math.BigDecimal; + +public final class LazilyParsedNumber +extends Number { + private final String value; + + public LazilyParsedNumber(String value) { + this.value = value; + } + + public int intValue() { + try { + return Integer.parseInt(this.value); + } + catch (NumberFormatException e) { + try { + return (int)Long.parseLong(this.value); + } + catch (NumberFormatException nfe) { + return new BigDecimal(this.value).intValue(); + } + } + } + + public long longValue() { + try { + return Long.parseLong(this.value); + } + catch (NumberFormatException e) { + return new BigDecimal(this.value).longValue(); + } + } + + public float floatValue() { + return Float.parseFloat(this.value); + } + + public double doubleValue() { + return Double.parseDouble(this.value); + } + + public String toString() { + return this.value; + } + + private Object writeReplace() throws ObjectStreamException { + return new BigDecimal(this.value); + } +} diff --git a/src/com/google/gson/internal/LinkedTreeMap.java b/src/com/google/gson/internal/LinkedTreeMap.java new file mode 100644 index 0000000..f8643df --- /dev/null +++ b/src/com/google/gson/internal/LinkedTreeMap.java @@ -0,0 +1,540 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class LinkedTreeMap +extends AbstractMap +implements Serializable { + private static final Comparator NATURAL_ORDER = new Comparator(){ + + @Override + public int compare(Comparable a, Comparable b) { + return a.compareTo(b); + } + }; + Comparator comparator; + Node root; + int size = 0; + int modCount = 0; + final Node header = new Node(); + private EntrySet entrySet; + private KeySet keySet; + + public LinkedTreeMap() { + this(NATURAL_ORDER); + } + + public LinkedTreeMap(Comparator comparator) { + this.comparator = comparator != null ? comparator : NATURAL_ORDER; + } + + @Override + public int size() { + return this.size; + } + + @Override + public V get(Object key) { + Node node = this.findByObject(key); + return node != null ? (V)node.value : null; + } + + @Override + public boolean containsKey(Object key) { + return this.findByObject(key) != null; + } + + @Override + public V put(K key, V value) { + if (key == null) { + throw new NullPointerException("key == null"); + } + Node created = this.find(key, true); + Object result = created.value; + created.value = value; + return result; + } + + @Override + public void clear() { + this.root = null; + this.size = 0; + ++this.modCount; + Node header = this.header; + header.prev = header; + header.next = header.prev; + } + + @Override + public V remove(Object key) { + Node node = this.removeInternalByKey(key); + return node != null ? (V)node.value : null; + } + + Node find(K key, boolean create) { + Node created; + Comparator comparator = this.comparator; + Node nearest = this.root; + int comparison = 0; + if (nearest != null) { + Comparable comparableKey = comparator == NATURAL_ORDER ? (Comparable)key : null; + while (true) { + Node child; + int n = comparison = comparableKey != null ? comparableKey.compareTo(nearest.key) : comparator.compare(key, nearest.key); + if (comparison == 0) { + return nearest; + } + Node node = child = comparison < 0 ? nearest.left : nearest.right; + if (child == null) break; + nearest = child; + } + } + if (!create) { + return null; + } + Node header = this.header; + if (nearest == null) { + if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) { + throw new ClassCastException(key.getClass().getName() + " is not Comparable"); + } + created = new Node(nearest, key, header, header.prev); + this.root = created; + } else { + created = new Node(nearest, key, header, header.prev); + if (comparison < 0) { + nearest.left = created; + } else { + nearest.right = created; + } + this.rebalance(nearest, true); + } + ++this.size; + ++this.modCount; + return created; + } + + Node findByObject(Object key) { + try { + return key != null ? this.find(key, false) : null; + } + catch (ClassCastException e) { + return null; + } + } + + Node findByEntry(Map.Entry entry) { + Node mine = this.findByObject(entry.getKey()); + boolean valuesEqual = mine != null && this.equal(mine.value, entry.getValue()); + return valuesEqual ? mine : null; + } + + private boolean equal(Object a, Object b) { + return a == b || a != null && a.equals(b); + } + + void removeInternal(Node node, boolean unlink) { + if (unlink) { + node.prev.next = node.next; + node.next.prev = node.prev; + } + Node left = node.left; + Node right = node.right; + Node originalParent = node.parent; + if (left != null && right != null) { + Node adjacent = left.height > right.height ? left.last() : right.first(); + this.removeInternal(adjacent, false); + int leftHeight = 0; + left = node.left; + if (left != null) { + leftHeight = left.height; + adjacent.left = left; + left.parent = adjacent; + node.left = null; + } + int rightHeight = 0; + right = node.right; + if (right != null) { + rightHeight = right.height; + adjacent.right = right; + right.parent = adjacent; + node.right = null; + } + adjacent.height = Math.max(leftHeight, rightHeight) + 1; + this.replaceInParent(node, adjacent); + return; + } + if (left != null) { + this.replaceInParent(node, left); + node.left = null; + } else if (right != null) { + this.replaceInParent(node, right); + node.right = null; + } else { + this.replaceInParent(node, null); + } + this.rebalance(originalParent, false); + --this.size; + ++this.modCount; + } + + Node removeInternalByKey(Object key) { + Node node = this.findByObject(key); + if (node != null) { + this.removeInternal(node, true); + } + return node; + } + + private void replaceInParent(Node node, Node replacement) { + Node parent = node.parent; + node.parent = null; + if (replacement != null) { + replacement.parent = parent; + } + if (parent != null) { + if (parent.left == node) { + parent.left = replacement; + } else { + assert (parent.right == node); + parent.right = replacement; + } + } else { + this.root = replacement; + } + } + + private void rebalance(Node unbalanced, boolean insert) { + Node node = unbalanced; + while (node != null) { + Node right; + int rightHeight; + Node left = node.left; + int leftHeight = left != null ? left.height : 0; + int delta = leftHeight - (rightHeight = (right = node.right) != null ? right.height : 0); + if (delta == -2) { + Node rightRight; + int rightRightHeight; + Node rightLeft = right.left; + int rightLeftHeight = rightLeft != null ? rightLeft.height : 0; + int rightDelta = rightLeftHeight - (rightRightHeight = (rightRight = right.right) != null ? rightRight.height : 0); + if (rightDelta == -1 || rightDelta == 0 && !insert) { + this.rotateLeft(node); + } else { + assert (rightDelta == 1); + this.rotateRight(right); + this.rotateLeft(node); + } + if (insert) { + break; + } + } else if (delta == 2) { + Node leftRight; + int leftRightHeight; + Node leftLeft = left.left; + int leftLeftHeight = leftLeft != null ? leftLeft.height : 0; + int leftDelta = leftLeftHeight - (leftRightHeight = (leftRight = left.right) != null ? leftRight.height : 0); + if (leftDelta == 1 || leftDelta == 0 && !insert) { + this.rotateRight(node); + } else { + assert (leftDelta == -1); + this.rotateLeft(left); + this.rotateRight(node); + } + if (insert) { + break; + } + } else if (delta == 0) { + node.height = leftHeight + 1; + if (insert) { + break; + } + } else { + assert (delta == -1 || delta == 1); + node.height = Math.max(leftHeight, rightHeight) + 1; + if (!insert) break; + } + node = node.parent; + } + } + + private void rotateLeft(Node root) { + Node left = root.left; + Node pivot = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + root.right = pivotLeft; + if (pivotLeft != null) { + pivotLeft.parent = root; + } + this.replaceInParent(root, pivot); + pivot.left = root; + root.parent = pivot; + root.height = Math.max(left != null ? left.height : 0, pivotLeft != null ? pivotLeft.height : 0) + 1; + pivot.height = Math.max(root.height, pivotRight != null ? pivotRight.height : 0) + 1; + } + + private void rotateRight(Node root) { + Node pivot = root.left; + Node right = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + root.left = pivotRight; + if (pivotRight != null) { + pivotRight.parent = root; + } + this.replaceInParent(root, pivot); + pivot.right = root; + root.parent = pivot; + root.height = Math.max(right != null ? right.height : 0, pivotRight != null ? pivotRight.height : 0) + 1; + pivot.height = Math.max(root.height, pivotLeft != null ? pivotLeft.height : 0) + 1; + } + + @Override + public Set> entrySet() { + EntrySet result = this.entrySet; + return result != null ? result : (this.entrySet = new EntrySet()); + } + + @Override + public Set keySet() { + KeySet result = this.keySet; + return result != null ? result : (this.keySet = new KeySet()); + } + + private Object writeReplace() throws ObjectStreamException { + return new LinkedHashMap(this); + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + class KeySet + extends AbstractSet { + KeySet() { + } + + @Override + public int size() { + return LinkedTreeMap.this.size; + } + + @Override + public Iterator iterator() { + return new LinkedTreeMapIterator(){ + + @Override + public K next() { + return this.nextNode().key; + } + }; + } + + @Override + public boolean contains(Object o) { + return LinkedTreeMap.this.containsKey(o); + } + + @Override + public boolean remove(Object key) { + return LinkedTreeMap.this.removeInternalByKey(key) != null; + } + + @Override + public void clear() { + LinkedTreeMap.this.clear(); + } + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + class EntrySet + extends AbstractSet> { + EntrySet() { + } + + @Override + public int size() { + return LinkedTreeMap.this.size; + } + + @Override + public Iterator> iterator() { + return new LinkedTreeMapIterator>(){ + + @Override + public Map.Entry next() { + return this.nextNode(); + } + }; + } + + @Override + public boolean contains(Object o) { + return o instanceof Map.Entry && LinkedTreeMap.this.findByEntry((Map.Entry)o) != null; + } + + @Override + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) { + return false; + } + Node node = LinkedTreeMap.this.findByEntry((Map.Entry)o); + if (node == null) { + return false; + } + LinkedTreeMap.this.removeInternal(node, true); + return true; + } + + @Override + public void clear() { + LinkedTreeMap.this.clear(); + } + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + private abstract class LinkedTreeMapIterator + implements Iterator { + Node next; + Node lastReturned; + int expectedModCount; + + private LinkedTreeMapIterator() { + this.next = LinkedTreeMap.this.header.next; + this.lastReturned = null; + this.expectedModCount = LinkedTreeMap.this.modCount; + } + + @Override + public final boolean hasNext() { + return this.next != LinkedTreeMap.this.header; + } + + final Node nextNode() { + Node e = this.next; + if (e == LinkedTreeMap.this.header) { + throw new NoSuchElementException(); + } + if (LinkedTreeMap.this.modCount != this.expectedModCount) { + throw new ConcurrentModificationException(); + } + this.next = e.next; + this.lastReturned = e; + return this.lastReturned; + } + + @Override + public final void remove() { + if (this.lastReturned == null) { + throw new IllegalStateException(); + } + LinkedTreeMap.this.removeInternal(this.lastReturned, true); + this.lastReturned = null; + this.expectedModCount = LinkedTreeMap.this.modCount; + } + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + static final class Node + implements Map.Entry { + Node parent; + Node left; + Node right; + Node next; + Node prev; + final K key; + V value; + int height; + + Node() { + this.key = null; + this.next = this.prev = this; + } + + Node(Node parent, K key, Node next, Node prev) { + this.parent = parent; + this.key = key; + this.height = 1; + this.next = next; + this.prev = prev; + prev.next = this; + next.prev = this; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public V getValue() { + return this.value; + } + + @Override + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry other = (Map.Entry)o; + return (this.key == null ? other.getKey() == null : this.key.equals(other.getKey())) && (this.value == null ? other.getValue() == null : this.value.equals(other.getValue())); + } + return false; + } + + @Override + public int hashCode() { + return (this.key == null ? 0 : this.key.hashCode()) ^ (this.value == null ? 0 : this.value.hashCode()); + } + + public String toString() { + return this.key + "=" + this.value; + } + + public Node first() { + Node node = this; + Node child = node.left; + while (child != null) { + node = child; + child = node.left; + } + return node; + } + + public Node last() { + Node node = this; + Node child = node.right; + while (child != null) { + node = child; + child = node.right; + } + return node; + } + } +} diff --git a/src/com/google/gson/internal/ObjectConstructor.java b/src/com/google/gson/internal/ObjectConstructor.java new file mode 100644 index 0000000..5c0e763 --- /dev/null +++ b/src/com/google/gson/internal/ObjectConstructor.java @@ -0,0 +1,11 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public interface ObjectConstructor { + public T construct(); +} diff --git a/src/com/google/gson/internal/Primitives.java b/src/com/google/gson/internal/Primitives.java new file mode 100644 index 0000000..8b82a70 --- /dev/null +++ b/src/com/google/gson/internal/Primitives.java @@ -0,0 +1,60 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import com.google.gson.internal.$Gson$Preconditions; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class Primitives { + private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPE; + + private Primitives() { + } + + private static void add(Map, Class> forward, Map, Class> backward, Class key, Class value) { + forward.put(key, value); + backward.put(value, key); + } + + public static boolean isPrimitive(Type type) { + return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type); + } + + public static boolean isWrapperType(Type type) { + return WRAPPER_TO_PRIMITIVE_TYPE.containsKey($Gson$Preconditions.checkNotNull(type)); + } + + public static Class wrap(Class type) { + Class wrapped = PRIMITIVE_TO_WRAPPER_TYPE.get($Gson$Preconditions.checkNotNull(type)); + return wrapped == null ? type : wrapped; + } + + public static Class unwrap(Class type) { + Class unwrapped = WRAPPER_TO_PRIMITIVE_TYPE.get($Gson$Preconditions.checkNotNull(type)); + return unwrapped == null ? type : unwrapped; + } + + static { + HashMap primToWrap = new HashMap(16); + HashMap wrapToPrim = new HashMap(16); + Primitives.add(primToWrap, wrapToPrim, Boolean.TYPE, Boolean.class); + Primitives.add(primToWrap, wrapToPrim, Byte.TYPE, Byte.class); + Primitives.add(primToWrap, wrapToPrim, Character.TYPE, Character.class); + Primitives.add(primToWrap, wrapToPrim, Double.TYPE, Double.class); + Primitives.add(primToWrap, wrapToPrim, Float.TYPE, Float.class); + Primitives.add(primToWrap, wrapToPrim, Integer.TYPE, Integer.class); + Primitives.add(primToWrap, wrapToPrim, Long.TYPE, Long.class); + Primitives.add(primToWrap, wrapToPrim, Short.TYPE, Short.class); + Primitives.add(primToWrap, wrapToPrim, Void.TYPE, Void.class); + PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim); + } +} diff --git a/src/com/google/gson/internal/Streams.java b/src/com/google/gson/internal/Streams.java new file mode 100644 index 0000000..94cfd1f --- /dev/null +++ b/src/com/google/gson/internal/Streams.java @@ -0,0 +1,96 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Writer; + +public final class Streams { + public static JsonElement parse(JsonReader reader) throws JsonParseException { + boolean isEmpty = true; + try { + reader.peek(); + isEmpty = false; + return TypeAdapters.JSON_ELEMENT.read(reader); + } + catch (EOFException e) { + if (isEmpty) { + return JsonNull.INSTANCE; + } + throw new JsonSyntaxException(e); + } + catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonIOException(e); + } + catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + public static void write(JsonElement element, JsonWriter writer) throws IOException { + TypeAdapters.JSON_ELEMENT.write(writer, element); + } + + public static Writer writerForAppendable(Appendable appendable) { + return appendable instanceof Writer ? (Writer)appendable : new AppendableWriter(appendable); + } + + private static final class AppendableWriter + extends Writer { + private final Appendable appendable; + private final CurrentWrite currentWrite = new CurrentWrite(); + + private AppendableWriter(Appendable appendable) { + this.appendable = appendable; + } + + public void write(char[] chars, int offset, int length) throws IOException { + this.currentWrite.chars = chars; + this.appendable.append(this.currentWrite, offset, offset + length); + } + + public void write(int i) throws IOException { + this.appendable.append((char)i); + } + + public void flush() { + } + + public void close() { + } + + static class CurrentWrite + implements CharSequence { + char[] chars; + + CurrentWrite() { + } + + public int length() { + return this.chars.length; + } + + public char charAt(int i) { + return this.chars[i]; + } + + public CharSequence subSequence(int start, int end) { + return new String(this.chars, start, end - start); + } + } + } +} diff --git a/src/com/google/gson/internal/UnsafeAllocator.java b/src/com/google/gson/internal/UnsafeAllocator.java new file mode 100644 index 0000000..6b79a89 --- /dev/null +++ b/src/com/google/gson/internal/UnsafeAllocator.java @@ -0,0 +1,71 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal; + +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public abstract class UnsafeAllocator { + public abstract T newInstance(Class var1) throws Exception; + + public static UnsafeAllocator create() { + try { + Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Field f = unsafeClass.getDeclaredField("theUnsafe"); + f.setAccessible(true); + final Object unsafe = f.get(null); + final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class); + return new UnsafeAllocator(){ + + @Override + public T newInstance(Class c) throws Exception { + return (T)allocateInstance.invoke(unsafe, c); + } + }; + } + catch (Exception ignored) { + try { + final Method newInstance = ObjectInputStream.class.getDeclaredMethod("newInstance", Class.class, Class.class); + newInstance.setAccessible(true); + return new UnsafeAllocator(){ + + @Override + public T newInstance(Class c) throws Exception { + return (T)newInstance.invoke(null, c, Object.class); + } + }; + } + catch (Exception ignored2) { + try { + Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod("getConstructorId", Class.class); + getConstructorId.setAccessible(true); + final int constructorId = (Integer)getConstructorId.invoke(null, Object.class); + final Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance", Class.class, Integer.TYPE); + newInstance.setAccessible(true); + return new UnsafeAllocator(){ + + @Override + public T newInstance(Class c) throws Exception { + return (T)newInstance.invoke(null, c, constructorId); + } + }; + } + catch (Exception exception) { + return new UnsafeAllocator(){ + + @Override + public T newInstance(Class c) { + throw new UnsupportedOperationException("Cannot allocate " + c); + } + }; + } + } + } + } +} diff --git a/src/com/google/gson/internal/bind/ArrayTypeAdapter.java b/src/com/google/gson/internal/bind/ArrayTypeAdapter.java new file mode 100644 index 0000000..4cb3b47 --- /dev/null +++ b/src/com/google/gson/internal/bind/ArrayTypeAdapter.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Types; +import com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Type; +import java.util.ArrayList; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class ArrayTypeAdapter +extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory(){ + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + if (!(type instanceof GenericArrayType || type instanceof Class && ((Class)type).isArray())) { + return null; + } + Type componentType = $Gson$Types.getArrayComponentType(type); + TypeAdapter componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType)); + return new ArrayTypeAdapter(gson, componentTypeAdapter, $Gson$Types.getRawType(componentType)); + } + }; + private final Class componentType; + private final TypeAdapter componentTypeAdapter; + + public ArrayTypeAdapter(Gson context, TypeAdapter componentTypeAdapter, Class componentType) { + this.componentTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, componentTypeAdapter, componentType); + this.componentType = componentType; + } + + @Override + public Object read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + ArrayList list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + E instance = this.componentTypeAdapter.read(in); + list.add(instance); + } + in.endArray(); + Object array = Array.newInstance(this.componentType, list.size()); + for (int i = 0; i < list.size(); ++i) { + Array.set(array, i, list.get(i)); + } + return array; + } + + @Override + public void write(JsonWriter out, Object array) throws IOException { + if (array == null) { + out.nullValue(); + return; + } + out.beginArray(); + int length = Array.getLength(array); + for (int i = 0; i < length; ++i) { + Object value = Array.get(array, i); + this.componentTypeAdapter.write(out, value); + } + out.endArray(); + } +} diff --git a/src/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/src/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java new file mode 100644 index 0000000..0129abb --- /dev/null +++ b/src/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java @@ -0,0 +1,88 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class CollectionTypeAdapterFactory +implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + + public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) { + this.constructorConstructor = constructorConstructor; + } + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + Class rawType = typeToken.getRawType(); + if (!Collection.class.isAssignableFrom(rawType)) { + return null; + } + Type elementType = $Gson$Types.getCollectionElementType(type, rawType); + TypeAdapter elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); + ObjectConstructor constructor = this.constructorConstructor.get(typeToken); + Adapter result = new Adapter(gson, elementType, elementTypeAdapter, constructor); + return result; + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + private static final class Adapter + extends TypeAdapter> { + private final TypeAdapter elementTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Gson context, Type elementType, TypeAdapter elementTypeAdapter, ObjectConstructor> constructor) { + this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, elementTypeAdapter, elementType); + this.constructor = constructor; + } + + @Override + public Collection read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + Collection collection = this.constructor.construct(); + in.beginArray(); + while (in.hasNext()) { + E instance = this.elementTypeAdapter.read(in); + collection.add(instance); + } + in.endArray(); + return collection; + } + + @Override + public void write(JsonWriter out, Collection collection) throws IOException { + if (collection == null) { + out.nullValue(); + return; + } + out.beginArray(); + for (E element : collection) { + this.elementTypeAdapter.write(out, element); + } + out.endArray(); + } + } +} diff --git a/src/com/google/gson/internal/bind/DateTypeAdapter.java b/src/com/google/gson/internal/bind/DateTypeAdapter.java new file mode 100644 index 0000000..84274c4 --- /dev/null +++ b/src/com/google/gson/internal/bind/DateTypeAdapter.java @@ -0,0 +1,81 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class DateTypeAdapter +extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory(){ + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == Date.class ? new DateTypeAdapter() : null; + } + }; + private final DateFormat enUsFormat = DateFormat.getDateTimeInstance(2, 2, Locale.US); + private final DateFormat localFormat = DateFormat.getDateTimeInstance(2, 2); + private final DateFormat iso8601Format = DateTypeAdapter.buildIso8601Format(); + + private static DateFormat buildIso8601Format() { + SimpleDateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); + return iso8601Format; + } + + @Override + public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return this.deserializeToDate(in.nextString()); + } + + private synchronized Date deserializeToDate(String json) { + try { + return this.localFormat.parse(json); + } + catch (ParseException ignored) { + try { + return this.enUsFormat.parse(json); + } + catch (ParseException ignored2) { + try { + return this.iso8601Format.parse(json); + } + catch (ParseException e) { + throw new JsonSyntaxException(json, e); + } + } + } + } + + @Override + public synchronized void write(JsonWriter out, Date value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + String dateFormatAsString = this.enUsFormat.format(value); + out.value(dateFormatAsString); + } +} diff --git a/src/com/google/gson/internal/bind/JsonTreeReader.java b/src/com/google/gson/internal/bind/JsonTreeReader.java new file mode 100644 index 0000000..0f999cf --- /dev/null +++ b/src/com/google/gson/internal/bind/JsonTreeReader.java @@ -0,0 +1,211 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public final class JsonTreeReader +extends JsonReader { + private static final Reader UNREADABLE_READER = new Reader(){ + + public int read(char[] buffer, int offset, int count) throws IOException { + throw new AssertionError(); + } + + public void close() throws IOException { + throw new AssertionError(); + } + }; + private static final Object SENTINEL_CLOSED = new Object(); + private final List stack = new ArrayList(); + + public JsonTreeReader(JsonElement element) { + super(UNREADABLE_READER); + this.stack.add(element); + } + + public void beginArray() throws IOException { + this.expect(JsonToken.BEGIN_ARRAY); + JsonArray array = (JsonArray)this.peekStack(); + this.stack.add(array.iterator()); + } + + public void endArray() throws IOException { + this.expect(JsonToken.END_ARRAY); + this.popStack(); + this.popStack(); + } + + public void beginObject() throws IOException { + this.expect(JsonToken.BEGIN_OBJECT); + JsonObject object = (JsonObject)this.peekStack(); + this.stack.add(object.entrySet().iterator()); + } + + public void endObject() throws IOException { + this.expect(JsonToken.END_OBJECT); + this.popStack(); + this.popStack(); + } + + public boolean hasNext() throws IOException { + JsonToken token = this.peek(); + return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY; + } + + public JsonToken peek() throws IOException { + if (this.stack.isEmpty()) { + return JsonToken.END_DOCUMENT; + } + Object o = this.peekStack(); + if (o instanceof Iterator) { + boolean isObject = this.stack.get(this.stack.size() - 2) instanceof JsonObject; + Iterator iterator = (Iterator)o; + if (iterator.hasNext()) { + if (isObject) { + return JsonToken.NAME; + } + this.stack.add(iterator.next()); + return this.peek(); + } + return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; + } + if (o instanceof JsonObject) { + return JsonToken.BEGIN_OBJECT; + } + if (o instanceof JsonArray) { + return JsonToken.BEGIN_ARRAY; + } + if (o instanceof JsonPrimitive) { + JsonPrimitive primitive = (JsonPrimitive)o; + if (primitive.isString()) { + return JsonToken.STRING; + } + if (primitive.isBoolean()) { + return JsonToken.BOOLEAN; + } + if (primitive.isNumber()) { + return JsonToken.NUMBER; + } + throw new AssertionError(); + } + if (o instanceof JsonNull) { + return JsonToken.NULL; + } + if (o == SENTINEL_CLOSED) { + throw new IllegalStateException("JsonReader is closed"); + } + throw new AssertionError(); + } + + private Object peekStack() { + return this.stack.get(this.stack.size() - 1); + } + + private Object popStack() { + return this.stack.remove(this.stack.size() - 1); + } + + private void expect(JsonToken expected) throws IOException { + if (this.peek() != expected) { + throw new IllegalStateException("Expected " + (Object)((Object)expected) + " but was " + (Object)((Object)this.peek())); + } + } + + public String nextName() throws IOException { + this.expect(JsonToken.NAME); + Iterator i = (Iterator)this.peekStack(); + Map.Entry entry = (Map.Entry)i.next(); + this.stack.add(entry.getValue()); + return (String)entry.getKey(); + } + + public String nextString() throws IOException { + JsonToken token = this.peek(); + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { + throw new IllegalStateException("Expected " + (Object)((Object)JsonToken.STRING) + " but was " + (Object)((Object)token)); + } + return ((JsonPrimitive)this.popStack()).getAsString(); + } + + public boolean nextBoolean() throws IOException { + this.expect(JsonToken.BOOLEAN); + return ((JsonPrimitive)this.popStack()).getAsBoolean(); + } + + public void nextNull() throws IOException { + this.expect(JsonToken.NULL); + this.popStack(); + } + + public double nextDouble() throws IOException { + JsonToken token = this.peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException("Expected " + (Object)((Object)JsonToken.NUMBER) + " but was " + (Object)((Object)token)); + } + double result = ((JsonPrimitive)this.peekStack()).getAsDouble(); + if (!this.isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) { + throw new NumberFormatException("JSON forbids NaN and infinities: " + result); + } + this.popStack(); + return result; + } + + public long nextLong() throws IOException { + JsonToken token = this.peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException("Expected " + (Object)((Object)JsonToken.NUMBER) + " but was " + (Object)((Object)token)); + } + long result = ((JsonPrimitive)this.peekStack()).getAsLong(); + this.popStack(); + return result; + } + + public int nextInt() throws IOException { + JsonToken token = this.peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException("Expected " + (Object)((Object)JsonToken.NUMBER) + " but was " + (Object)((Object)token)); + } + int result = ((JsonPrimitive)this.peekStack()).getAsInt(); + this.popStack(); + return result; + } + + public void close() throws IOException { + this.stack.clear(); + this.stack.add(SENTINEL_CLOSED); + } + + public void skipValue() throws IOException { + if (this.peek() == JsonToken.NAME) { + this.nextName(); + } else { + this.popStack(); + } + } + + public String toString() { + return this.getClass().getSimpleName(); + } + + public void promoteNameToValue() throws IOException { + this.expect(JsonToken.NAME); + Iterator i = (Iterator)this.peekStack(); + Map.Entry entry = (Map.Entry)i.next(); + this.stack.add(entry.getValue()); + this.stack.add(new JsonPrimitive((String)entry.getKey())); + } +} diff --git a/src/com/google/gson/internal/bind/JsonTreeWriter.java b/src/com/google/gson/internal/bind/JsonTreeWriter.java new file mode 100644 index 0000000..8ffb081 --- /dev/null +++ b/src/com/google/gson/internal/bind/JsonTreeWriter.java @@ -0,0 +1,174 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +public final class JsonTreeWriter +extends JsonWriter { + private static final Writer UNWRITABLE_WRITER = new Writer(){ + + public void write(char[] buffer, int offset, int counter) { + throw new AssertionError(); + } + + public void flush() throws IOException { + throw new AssertionError(); + } + + public void close() throws IOException { + throw new AssertionError(); + } + }; + private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed"); + private final List stack = new ArrayList(); + private String pendingName; + private JsonElement product = JsonNull.INSTANCE; + + public JsonTreeWriter() { + super(UNWRITABLE_WRITER); + } + + public JsonElement get() { + if (!this.stack.isEmpty()) { + throw new IllegalStateException("Expected one JSON element but was " + this.stack); + } + return this.product; + } + + private JsonElement peek() { + return this.stack.get(this.stack.size() - 1); + } + + private void put(JsonElement value) { + if (this.pendingName != null) { + if (!value.isJsonNull() || this.getSerializeNulls()) { + JsonObject object = (JsonObject)this.peek(); + object.add(this.pendingName, value); + } + this.pendingName = null; + } else if (this.stack.isEmpty()) { + this.product = value; + } else { + JsonElement element = this.peek(); + if (element instanceof JsonArray) { + ((JsonArray)element).add(value); + } else { + throw new IllegalStateException(); + } + } + } + + public JsonWriter beginArray() throws IOException { + JsonArray array = new JsonArray(); + this.put(array); + this.stack.add(array); + return this; + } + + public JsonWriter endArray() throws IOException { + if (this.stack.isEmpty() || this.pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = this.peek(); + if (element instanceof JsonArray) { + this.stack.remove(this.stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter beginObject() throws IOException { + JsonObject object = new JsonObject(); + this.put(object); + this.stack.add(object); + return this; + } + + public JsonWriter endObject() throws IOException { + if (this.stack.isEmpty() || this.pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = this.peek(); + if (element instanceof JsonObject) { + this.stack.remove(this.stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter name(String name) throws IOException { + if (this.stack.isEmpty() || this.pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = this.peek(); + if (element instanceof JsonObject) { + this.pendingName = name; + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter value(String value) throws IOException { + if (value == null) { + return this.nullValue(); + } + this.put(new JsonPrimitive(value)); + return this; + } + + public JsonWriter nullValue() throws IOException { + this.put(JsonNull.INSTANCE); + return this; + } + + public JsonWriter value(boolean value) throws IOException { + this.put(new JsonPrimitive(value)); + return this; + } + + public JsonWriter value(double value) throws IOException { + if (!this.isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + this.put(new JsonPrimitive(value)); + return this; + } + + public JsonWriter value(long value) throws IOException { + this.put(new JsonPrimitive(value)); + return this; + } + + public JsonWriter value(Number value) throws IOException { + double d; + if (value == null) { + return this.nullValue(); + } + if (!this.isLenient() && (Double.isNaN(d = value.doubleValue()) || Double.isInfinite(d))) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + this.put(new JsonPrimitive(value)); + return this; + } + + public void flush() throws IOException { + } + + public void close() throws IOException { + if (!this.stack.isEmpty()) { + throw new IOException("Incomplete document"); + } + this.stack.add(SENTINEL_CLOSED); + } +} diff --git a/src/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/src/com/google/gson/internal/bind/MapTypeAdapterFactory.java new file mode 100644 index 0000000..afdd323 --- /dev/null +++ b/src/com/google/gson/internal/bind/MapTypeAdapterFactory.java @@ -0,0 +1,176 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.JsonReaderInternalAccess; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.Streams; +import com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Map; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class MapTypeAdapterFactory +implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + private final boolean complexMapKeySerialization; + + public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor, boolean complexMapKeySerialization) { + this.constructorConstructor = constructorConstructor; + this.complexMapKeySerialization = complexMapKeySerialization; + } + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + Class rawType = typeToken.getRawType(); + if (!Map.class.isAssignableFrom(rawType)) { + return null; + } + Class rawTypeOfSrc = $Gson$Types.getRawType(type); + Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc); + TypeAdapter keyAdapter = this.getKeyAdapter(gson, keyAndValueTypes[0]); + TypeAdapter valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1])); + ObjectConstructor constructor = this.constructorConstructor.get(typeToken); + Adapter result = new Adapter(gson, keyAndValueTypes[0], keyAdapter, keyAndValueTypes[1], valueAdapter, constructor); + return result; + } + + private TypeAdapter getKeyAdapter(Gson context, Type keyType) { + return keyType == Boolean.TYPE || keyType == Boolean.class ? TypeAdapters.BOOLEAN_AS_STRING : context.getAdapter(TypeToken.get(keyType)); + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + private final class Adapter + extends TypeAdapter> { + private final TypeAdapter keyTypeAdapter; + private final TypeAdapter valueTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Gson context, Type keyType, TypeAdapter keyTypeAdapter, Type valueType, TypeAdapter valueTypeAdapter, ObjectConstructor> constructor) { + this.keyTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, keyTypeAdapter, keyType); + this.valueTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, valueTypeAdapter, valueType); + this.constructor = constructor; + } + + @Override + public Map read(JsonReader in) throws IOException { + JsonToken peek = in.peek(); + if (peek == JsonToken.NULL) { + in.nextNull(); + return null; + } + Map map = this.constructor.construct(); + if (peek == JsonToken.BEGIN_ARRAY) { + in.beginArray(); + while (in.hasNext()) { + in.beginArray(); + K key = this.keyTypeAdapter.read(in); + V value = this.valueTypeAdapter.read(in); + V replaced = map.put(key, value); + if (replaced != null) { + throw new JsonSyntaxException("duplicate key: " + key); + } + in.endArray(); + } + in.endArray(); + } else { + in.beginObject(); + while (in.hasNext()) { + V value; + JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); + K key = this.keyTypeAdapter.read(in); + V replaced = map.put(key, value = this.valueTypeAdapter.read(in)); + if (replaced == null) continue; + throw new JsonSyntaxException("duplicate key: " + key); + } + in.endObject(); + } + return map; + } + + @Override + public void write(JsonWriter out, Map map) throws IOException { + if (map == null) { + out.nullValue(); + return; + } + if (!MapTypeAdapterFactory.this.complexMapKeySerialization) { + out.beginObject(); + for (Map.Entry entry : map.entrySet()) { + out.name(String.valueOf(entry.getKey())); + this.valueTypeAdapter.write(out, entry.getValue()); + } + out.endObject(); + return; + } + boolean hasComplexKeys = false; + ArrayList keys = new ArrayList(map.size()); + ArrayList values = new ArrayList(map.size()); + for (Map.Entry entry : map.entrySet()) { + JsonElement keyElement = this.keyTypeAdapter.toJsonTree(entry.getKey()); + keys.add(keyElement); + values.add(entry.getValue()); + hasComplexKeys |= keyElement.isJsonArray() || keyElement.isJsonObject(); + } + if (hasComplexKeys) { + out.beginArray(); + for (int i = 0; i < keys.size(); ++i) { + out.beginArray(); + Streams.write((JsonElement)keys.get(i), out); + this.valueTypeAdapter.write(out, values.get(i)); + out.endArray(); + } + out.endArray(); + } else { + out.beginObject(); + for (int i = 0; i < keys.size(); ++i) { + JsonElement keyElement = (JsonElement)keys.get(i); + out.name(this.keyToString(keyElement)); + this.valueTypeAdapter.write(out, values.get(i)); + } + out.endObject(); + } + } + + private String keyToString(JsonElement keyElement) { + if (keyElement.isJsonPrimitive()) { + JsonPrimitive primitive = keyElement.getAsJsonPrimitive(); + if (primitive.isNumber()) { + return String.valueOf(primitive.getAsNumber()); + } + if (primitive.isBoolean()) { + return Boolean.toString(primitive.getAsBoolean()); + } + if (primitive.isString()) { + return primitive.getAsString(); + } + throw new AssertionError(); + } + if (keyElement.isJsonNull()) { + return "null"; + } + throw new AssertionError(); + } + } +} diff --git a/src/com/google/gson/internal/bind/ObjectTypeAdapter.java b/src/com/google/gson/internal/bind/ObjectTypeAdapter.java new file mode 100644 index 0000000..fdb697c --- /dev/null +++ b/src/com/google/gson/internal/bind/ObjectTypeAdapter.java @@ -0,0 +1,91 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.LinkedTreeMap; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.ArrayList; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class ObjectTypeAdapter +extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory(){ + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() == Object.class) { + return new ObjectTypeAdapter(gson); + } + return null; + } + }; + private final Gson gson; + + private ObjectTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override + public Object read(JsonReader in) throws IOException { + JsonToken token = in.peek(); + switch (token) { + case BEGIN_ARRAY: { + ArrayList list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + list.add(this.read(in)); + } + in.endArray(); + return list; + } + case BEGIN_OBJECT: { + LinkedTreeMap map = new LinkedTreeMap(); + in.beginObject(); + while (in.hasNext()) { + map.put(in.nextName(), this.read(in)); + } + in.endObject(); + return map; + } + case STRING: { + return in.nextString(); + } + case NUMBER: { + return in.nextDouble(); + } + case BOOLEAN: { + return in.nextBoolean(); + } + case NULL: { + in.nextNull(); + return null; + } + } + throw new IllegalStateException(); + } + + @Override + public void write(JsonWriter out, Object value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + TypeAdapter typeAdapter = this.gson.getAdapter(value.getClass()); + if (typeAdapter instanceof ObjectTypeAdapter) { + out.beginObject(); + out.endObject(); + return; + } + typeAdapter.write(out, value); + } +} diff --git a/src/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/src/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java new file mode 100644 index 0000000..d78f5e5 --- /dev/null +++ b/src/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java @@ -0,0 +1,189 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.FieldNamingStrategy; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; +import com.google.gson.internal.$Gson$Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.Primitives; +import com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class ReflectiveTypeAdapterFactory +implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + private final FieldNamingStrategy fieldNamingPolicy; + private final Excluder excluder; + + public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor, FieldNamingStrategy fieldNamingPolicy, Excluder excluder) { + this.constructorConstructor = constructorConstructor; + this.fieldNamingPolicy = fieldNamingPolicy; + this.excluder = excluder; + } + + public boolean excludeField(Field f, boolean serialize) { + return !this.excluder.excludeClass(f.getType(), serialize) && !this.excluder.excludeField(f, serialize); + } + + private String getFieldName(Field f) { + SerializedName serializedName = f.getAnnotation(SerializedName.class); + return serializedName == null ? this.fieldNamingPolicy.translateName(f) : serializedName.value(); + } + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + Class raw = type.getRawType(); + if (!Object.class.isAssignableFrom(raw)) { + return null; + } + ObjectConstructor constructor = this.constructorConstructor.get(type); + return new Adapter(constructor, this.getBoundFields(gson, type, raw)); + } + + private BoundField createBoundField(final Gson context, final Field field, String name, final TypeToken fieldType, boolean serialize, boolean deserialize) { + final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType()); + return new BoundField(name, serialize, deserialize){ + final TypeAdapter typeAdapter; + { + super(x0, x1, x2); + this.typeAdapter = context.getAdapter(fieldType); + } + + void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException { + Object fieldValue = field.get(value); + TypeAdapterRuntimeTypeWrapper t = new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType()); + ((TypeAdapter)t).write(writer, fieldValue); + } + + void read(JsonReader reader, Object value) throws IOException, IllegalAccessException { + Object fieldValue = this.typeAdapter.read(reader); + if (fieldValue != null || !isPrimitive) { + field.set(value, fieldValue); + } + } + }; + } + + private Map getBoundFields(Gson context, TypeToken type, Class raw) { + LinkedHashMap result = new LinkedHashMap(); + if (raw.isInterface()) { + return result; + } + Type declaredType = type.getType(); + while (raw != Object.class) { + Field[] fields; + for (Field field : fields = raw.getDeclaredFields()) { + boolean serialize = this.excludeField(field, true); + boolean deserialize = this.excludeField(field, false); + if (!serialize && !deserialize) continue; + field.setAccessible(true); + Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); + BoundField boundField = this.createBoundField(context, field, this.getFieldName(field), TypeToken.get(fieldType), serialize, deserialize); + BoundField previous = result.put(boundField.name, boundField); + if (previous == null) continue; + throw new IllegalArgumentException(declaredType + " declares multiple JSON fields named " + previous.name); + } + type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass())); + raw = type.getRawType(); + } + return result; + } + + /* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ + public static final class Adapter + extends TypeAdapter { + private final ObjectConstructor constructor; + private final Map boundFields; + + private Adapter(ObjectConstructor constructor, Map boundFields) { + this.constructor = constructor; + this.boundFields = boundFields; + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + T instance = this.constructor.construct(); + try { + in.beginObject(); + while (in.hasNext()) { + String name = in.nextName(); + BoundField field = this.boundFields.get(name); + if (field == null || !field.deserialized) { + in.skipValue(); + continue; + } + field.read(in, instance); + } + } + catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } + catch (IllegalAccessException e) { + throw new AssertionError((Object)e); + } + in.endObject(); + return instance; + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.beginObject(); + try { + for (BoundField boundField : this.boundFields.values()) { + if (!boundField.serialized) continue; + out.name(boundField.name); + boundField.write(out, value); + } + } + catch (IllegalAccessException e) { + throw new AssertionError(); + } + out.endObject(); + } + } + + static abstract class BoundField { + final String name; + final boolean serialized; + final boolean deserialized; + + protected BoundField(String name, boolean serialized, boolean deserialized) { + this.name = name; + this.serialized = serialized; + this.deserialized = deserialized; + } + + abstract void write(JsonWriter var1, Object var2) throws IOException, IllegalAccessException; + + abstract void read(JsonReader var1, Object var2) throws IOException, IllegalAccessException; + } +} diff --git a/src/com/google/gson/internal/bind/SqlDateTypeAdapter.java b/src/com/google/gson/internal/bind/SqlDateTypeAdapter.java new file mode 100644 index 0000000..e2a8eff --- /dev/null +++ b/src/com/google/gson/internal/bind/SqlDateTypeAdapter.java @@ -0,0 +1,53 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.sql.Date; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class SqlDateTypeAdapter +extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory(){ + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == Date.class ? new SqlDateTypeAdapter() : null; + } + }; + private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); + + @Override + public synchronized Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + try { + long utilDate = this.format.parse(in.nextString()).getTime(); + return new Date(utilDate); + } + catch (ParseException e) { + throw new JsonSyntaxException(e); + } + } + + @Override + public synchronized void write(JsonWriter out, Date value) throws IOException { + out.value(value == null ? null : this.format.format(value)); + } +} diff --git a/src/com/google/gson/internal/bind/TimeTypeAdapter.java b/src/com/google/gson/internal/bind/TimeTypeAdapter.java new file mode 100644 index 0000000..bcb5163 --- /dev/null +++ b/src/com/google/gson/internal/bind/TimeTypeAdapter.java @@ -0,0 +1,54 @@ +/* + * Decompiled with CFR 0.152. + */ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.sql.Time; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/* + * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. + */ +public final class TimeTypeAdapter +extends TypeAdapter