예제 #1
0
def parseTagCompound(input, handler):
    """
    Reads a TAG_Compound from input.
    Calls handler.startCompound().
    For each entry in the TAG_Compound:
        1. Reads the type and name of the entry from input and calls handler.name()
        2. Calls an appropriate parse*() function (e.g. parseInt) to read the payload of the tag
    Finally, calls handler.endCompound().
    """
    handler.startCompound()

    #Read first named tag header
    tagType = _B.unpack(_r(input, 1))[0]
    while tagType != TAG_END:
        #Check that tagType is valid.
        _avtt(tagType)
        #Now that we know the named tag isn't TAG_End, read the name.
        #Call .name() on handler, passing tagType and the name string.
        handler.name(tagType, _rst(input))

        #Call appropriate parse() function for the type of tag we're reading
        TAG_PARSERS[tagType](input, handler)

        #Read next named tag header
        tagType = _B.unpack(_r(input, 1))[0]

    handler.endCompound()
예제 #2
0
def parseTagByteArray(input, handler):
    """
    Reads a TAG_Byte_Array from input.
    Calls handler.startByteArray(), passing the length of the array.
    Repeatedly reads up to 4KB from the array and calls handler.bytes(), passing the bytes that were read as an argument.
    Finally, calls handler.endByteArray().
    """
    length = _rah(input)

    handler.startByteArray(length)

    #Read at most 4096 bytes at a time
    if length > 0:
        while length > 4096:
            handler.bytes(_r(input, 4096))
            length -= 4096
        handler.bytes(_r(input, length))

    handler.endByteArray()
예제 #3
0
def _parseImpl(input, handler):
    """
    Implementation of parse().
    input is expected to be a readable file-like object containing uncompressed NBT data.
    See help( parse ) for further documentation.
    """
    #Read root tag type and name length at same time
    tagType, length = _NT.unpack(_r(input, 3))

    #Check that tagType and name length are valid.
    if tagType != TAG_COMPOUND:
        raise WrongTagError(TAG_COMPOUND, tagType)
    if length < 0:
        raise OutOfBoundsError(length, 0, 32768)

    #Call .name() on handler, passing tagType and length.
    try:
        handler.start()
        handler.name(tagType, _r(input, length).decode())
        parseTagCompound(input, handler)
        handler.end()
    except _StopParsingNBT:
        return False
    return True
예제 #4
0
    def _read( self, file ):
        """Read chunk contents from the given readable file-like object, file."""
        #Read chunk header
        file.seek( self.offset, os.SEEK_SET )

        size        = _rui( file ) - 1
        compression = _rub( file )

        if compression == 2:
            #TODO: Don't read entire file into memory; use zlib decompression objects
            source = BytesIO( zlib.decompress( _r( file, size ) ) )
        elif compression == 1:
            source = gzip.GzipFile( fileobj=file )
        else:
            raise NBTFormatError( "Unrecognized compression type: {:d}.".format( compression ) )

        #Read chunk data
        nbt = tag.read( source, None )

        self.size        = size
        self.compression = compression
        self.nbt         = nbt
예제 #5
0
def parseTagShort(input, handler):
    """
    Reads a TAG_Short from input as a python int.
    Calls handler.short() and passes the value as an argument.
    """
    handler.short(_S.unpack(_r(input, 2))[0])
예제 #6
0
def parseTagByte(input, handler):
    """
    Reads a TAG_Byte from input as a python int.
    Calls handler.byte() and passes the value as an argument.
    """
    handler.byte(_B.unpack(_r(input, 1))[0])
예제 #7
0
def parseTagDouble(input, handler):
    """
    Reads a TAG_Double from input as a python float (i.e. a double)
    Calls handler.double() and passes the value as an argument.
    """
    handler.double(_D.unpack(_r(input, 8))[0])
예제 #8
0
def parseTagFloat(input, handler):
    """
    Reads a TAG_Float from input as a python float (i.e. a float)
    Calls handler.float() and passes the value as an argument.
    """
    handler.float(_F.unpack(_r(input, 4))[0])
예제 #9
0
def parseTagLong(input, handler):
    """
    Reads a TAG_Long from input as a python int.
    Calls handler.long() and passes the value as an argument.
    """
    handler.long(_L.unpack(_r(input, 8))[0])
예제 #10
0
def parseTagInt(input, handler):
    """
    Reads a TAG_Int from input as a python int.
    Calls handler.int() and passes the value as an argument.
    """
    handler.int(_I.unpack(_r(input, 4))[0])
예제 #11
0
 def _r( i ):
     l = _rah( i )
     return TAG_Byte_Array( _r( i, l ) )