All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jnbt.NBTInputStream Maven / Gradle / Ivy

package org.jnbt;

/*
 * JNBT License
 * 
 * Copyright (c) 2010 Graham Edgecombe
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *       
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *       
 *     * Neither the name of the JNBT team nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE. 
 */
import com.google.common.io.LittleEndianDataInputStream;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 

This class reads NBT, or * Named Binary Tag streams, and produces an object graph of * subclasses of the Tag object.

* *

The NBT format was created by Markus Persson, and the specification may * be found at * http://www.minecraft.net/docs/NBT.txt.

* @author Graham Edgecombe * */ public final class NBTInputStream implements Closeable { /** * The data input stream. */ private final DataInput is; /** * Creates a new NBTInputStream, which will source its data * from the specified input stream, which is assumed to contain big * endian data, or if the input stream is already a {@link DataInput} * stream, the stream's default byte order. * * @param is The input stream. */ public NBTInputStream(InputStream is) { if (is instanceof DataInput) { this.is = (DataInput) is; } else { this.is = new DataInputStream(is); } } /** * Creates a new NBTInputStream, which will source its data * from the specified input stream. * * @param is The input stream. * @param littleEndian Whether the stream contains little endian data. */ public NBTInputStream(InputStream is, boolean littleEndian) { this.is = littleEndian ? new LittleEndianDataInputStream(is) : new DataInputStream(is); } /** * Reads an NBT tag from the stream. * @return The tag that was read. * @throws IOException if an I/O error occurs. */ public Tag readTag() throws IOException { return readTag(0); } /** * Reads an NBT from the stream. * @param depth The depth of this tag. * @return The tag that was read. * @throws IOException if an I/O error occurs. */ private Tag readTag(int depth) throws IOException { int type = is.readByte() & 0xFF; String name; if (type != NBTConstants.TYPE_END) { int nameLength = is.readShort() & 0xFFFF; byte[] nameBytes = new byte[nameLength]; is.readFully(nameBytes); name = new String(nameBytes, NBTConstants.CHARSET); } else { name = ""; } return readTagPayload(type, name, depth); } /** * Reads the payload of a tag, given the name and type. * @param type The type. * @param name The name. * @param depth The depth. * @return The tag. * @throws IOException if an I/O error occurs. */ private Tag readTagPayload(int type, String name, int depth) throws IOException { switch (type) { case NBTConstants.TYPE_END: // if (depth == 0) { // throw new IOException("TAG_End found without a TAG_Compound/TAG_List tag preceding it."); // } else { return new EndTag(); // } case NBTConstants.TYPE_BYTE: return new ByteTag(name, is.readByte()); case NBTConstants.TYPE_SHORT: return new ShortTag(name, is.readShort()); case NBTConstants.TYPE_INT: return new IntTag(name, is.readInt()); case NBTConstants.TYPE_LONG: return new LongTag(name, is.readLong()); case NBTConstants.TYPE_FLOAT: return new FloatTag(name, is.readFloat()); case NBTConstants.TYPE_DOUBLE: return new DoubleTag(name, is.readDouble()); case NBTConstants.TYPE_BYTE_ARRAY: int length = is.readInt(); byte[] bytes = new byte[length]; is.readFully(bytes); return new ByteArrayTag(name, bytes); case NBTConstants.TYPE_STRING: length = is.readShort(); bytes = new byte[length]; is.readFully(bytes); return new StringTag(name, new String(bytes, NBTConstants.CHARSET)); case NBTConstants.TYPE_LIST: int childType = is.readByte(); length = is.readInt(); List tagList = new ArrayList<>(); for (int i = 0; i < length; i++) { Tag tag = readTagPayload(childType, "", depth + 1); if (tag instanceof EndTag) { throw new IOException("TAG_End not permitted in a list."); } tagList.add(tag); } return new ListTag(name, NBTUtils.getTypeClass(childType), tagList); case NBTConstants.TYPE_COMPOUND: Map tagMap = new HashMap<>(); while (true) { Tag tag = readTag(depth + 1); if (tag instanceof EndTag) { break; } else { tagMap.put(tag.getName(), tag); } } return new CompoundTag(name, tagMap); case NBTConstants.TYPE_INT_ARRAY: length = is.readInt(); int[] values = new int[length]; for (int i = 0; i < length; i++) { values[i] = is.readInt(); } return new IntArrayTag(name, values); case NBTConstants.TYPE_LONG_ARRAY: length = is.readInt(); long[] longs = new long[length]; for (int i = 0; i < length; i++) { longs[i] = is.readLong(); } return new LongArrayTag(name, longs); default: throw new IOException("Invalid tag type: " + type + "."); } } public void close() throws IOException { ((InputStream) is).close(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy