SimpleJavaEngine/src/main/java/speiger/src/coreengine/utils/io/dataTag/special/MapTag.java

219 lines
5.3 KiB
Java

package speiger.src.coreengine.utils.io.dataTag.special;
import java.io.IOException;
import java.util.List;
import java.util.StringJoiner;
import java.util.function.Consumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap.Entry;
import speiger.src.collections.objects.sets.ObjectSet;
import speiger.src.collections.objects.utils.ObjectSets;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
import speiger.src.coreengine.utils.io.dataTag.DataTag;
import speiger.src.coreengine.utils.io.dataTag.compression.DataTagLimiter;
import speiger.src.coreengine.utils.io.dataTag.compression.TagCompressor;
import speiger.src.coreengine.utils.io.dataTag.compression.TagDecompressor;
import speiger.src.coreengine.utils.io.dataTag.simple.PrimitiveTag;
import speiger.src.coreengine.utils.io.dataTag.simple.StringTag;
import speiger.src.coreengine.utils.io.streams.ExtendedDataInput;
import speiger.src.coreengine.utils.io.streams.ExtendedDataOutput;
public class MapTag implements IMapTag
{
Object2ObjectMap<String, DataTag> tags = new Object2ObjectLinkedOpenHashMap<String, DataTag>();
public MapTag()
{
}
public MapTag(String id, DataTag tag)
{
if(tag instanceof ListTag) putList(id, tag.cast());
else if(tag instanceof MapTag) putMap(id, tag.cast());
else putTag(id, tag);
}
@Override
public int getId()
{
return 17;
}
@Override
public String getTypeName()
{
return "Map";
}
@Override
public long countBytes(long input)
{
input += 4;
for(Entry<String, DataTag> entry : Object2ObjectMaps.fastIterable(tags))
{
input += 1;
input = entry.getValue().countBytes(input);
}
return input;
}
@Override
public void addKeys(Consumer<String> keys)
{
for(Entry<String, DataTag> entry : Object2ObjectMaps.fastIterable(tags))
{
keys.accept(entry.getKey());
entry.getValue().addKeys(keys);
}
}
@Override
public void write(ExtendedDataOutput output, TagCompressor compressor) throws IOException
{
output.writeVarInt(tags.size());
for(Entry<String, DataTag> entry : Object2ObjectMaps.fastIterable(tags))
{
output.writeByte(entry.getValue().getId());
compressor.writeKey(entry.getKey());
entry.getValue().write(output, compressor);
}
}
@Override
public void read(ExtendedDataInput input, TagDecompressor decompressor, int depthLimit, DataTagLimiter limiter) throws IOException
{
if(depthLimit >= 512)
{
throw new IllegalStateException("Depth Limit Exceeded");
}
int size = input.readVarInt();
limiter.countBytes(4 + size);
for(int i = 0;i < size;i++)
{
byte type = input.readByte();
String id = decompressor.readKey();
limiter.countBytes(4 + (id.length() * 2));
tags.put(id, decompressor.readSubTag(type, id, depthLimit + 1));
}
}
@Override
public MapTag copy()
{
MapTag tag = new MapTag();
for(Entry<String, DataTag> entry : Object2ObjectMaps.fastIterable(tags))
{
tag.tags.put(entry.getKey(), entry.getValue().copy());
}
return tag;
}
@Override
public void putTag(String id, DataTag tag)
{
if(tag == null) return;
tags.put(id, tag);
}
public boolean contains(String id)
{
return tags.containsKey(id);
}
public boolean contains(String id, int tagType)
{
DataTag tag = tags.get(id);
return tag != null && ((tagType == 99 && tag instanceof PrimitiveTag) || tag.getId() == tagType);
}
@Override
public DataTag get(String id)
{
return tags.get(id);
}
public DataTag remove(String id)
{
return tags.remove(id);
}
public boolean isEmpty()
{
return tags.isEmpty();
}
public int size()
{
return tags.size();
}
public ObjectSet<String> keySet()
{
return ObjectSets.unmodifiable(tags.keySet());
}
public ObjectSet<Entry<String, DataTag>> entrySet()
{
return ObjectSets.unmodifiable(tags.object2ObjectEntrySet());
}
@Override
public int hashCode()
{
return tags.hashCode();
}
@Override
public boolean equals(Object obj)
{
return obj instanceof MapTag && ((MapTag)obj).tags.equals(tags);
}
@Override
public String toString()
{
StringJoiner joiner = new StringJoiner(",", "{", "}");
List<String> keys = new ObjectArrayList<>(tags.keySet());
keys.sort(null);
for(int i = 0, m = keys.size();i < m;i++)
{
joiner.add(StringTag.quoteAndEscapeBuilder(keys.get(i)).append(":").append(tags.get(keys.get(i))).toString());
}
return joiner.toString();
}
@Override
public String prettyPrint(String indent, int depth)
{
if(tags.isEmpty())
{
return "{}";
}
List<String> keys = new ObjectArrayList<>(tags.keySet());
keys.sort(null);
StringBuilder builder = new StringBuilder().append("{");
String s = DataTag.repeate(indent, depth+1);
if(!indent.isEmpty())
{
builder.append('\n');
}
for(int i = 0,m=keys.size();i<m;i++)
{
builder.append(s).append(KEY_HIGHLIGHT).append(keys.get(i)).append(RESET_HIGHLIGHT).append(": ").append(tags.get(keys.get(i)).prettyPrint(indent, depth+1));
if(i + 1 < m)
{
builder.append(",").append(indent.isEmpty() ? " " : '\n');
}
}
if(!indent.isEmpty())
{
builder.append('\n').append(DataTag.repeate(indent, depth));
}
builder.append("}");
return builder.toString();
}
}