Zerocode

From Second Life Wiki
Revision as of 01:43, 9 September 2024 by Wulfie Reanimator (talk | contribs) (Added a modern alternative.)
Jump to navigation Jump to search

zero encoding and decoding functions and a couple of useful functions from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399

# From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399
# From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399
def ByteToHex( byteStr ):
    """
    Convert a byte string to it's hex string representation e.g. for output.
    """
    
    # Uses list comprehension which is a fractionally faster implementation than
    # the alternative, more readable, implementation below
    #   
    #    hex = []
    #    for aChar in byteStr:
    #        hex.append( "%02X " % ord( aChar ) )
    #
    #    return ''.join( hex ).strip()        

    return ''.join( [ "%02X " % ord( x ) for x in byteStr ] ).strip()


def HexToByte( hexStr ):
    """
    Convert a string hex byte values into a byte string. The Hex Byte values may
    or may not be space separated.
    """
    # The list comprehension implementation is fractionally slower in this case    
    #
    #    hexStr = ''.join( hexStr.split(" ") )
    #    return ''.join( ["%c" % chr( int ( hexStr[i:i+2],16 ) ) \
    #                                   for i in range(0, len( hexStr ), 2) ] )
 
    bytes = []

    hexStr = ''.join( hexStr.split(" ") )

    for i in range(0, len(hexStr), 2):
        bytes.append( chr( int (hexStr[i:i+2], 16 ) ) )

    return ''.join( bytes )


def zero_encode(inputbuf):
    newstring =""
    zero = False
    zero_count = 0            
    for c in inputbuf:
        if c != '\0':
            if zero_count != 0:
                newstring = newstring + chr(zero_count)
                zero_count = 0
                zero = False

            newstring = newstring + c
            
        else:
            if zero == False:
                newstring = newstring + c
                zero = True
                
            zero_count = zero_count + 1
    if zero_count != 0:
        newstring = newstring + chr(zero_count)


    return newstring

def zero_decode(inputbuf):
    newstring =""
    in_zero = False
    for c in inputbuf:
        if c != '\0':
            if in_zero == True:
                zero_count = ord(c)
                zero_count = zero_count -1
                while zero_count>0:

                    newstring = newstring + '\0'
                    zero_count = zero_count -1
                in_zero = False
            else:
                newstring = newstring + c
        else:
            newstring = newstring + c
            in_zero = True
    return newstring

def zero_decode_ID(inputbuf):
    newstring =""
    in_zero = False
    #print "in encode, input is", ByteToHex(inputbuf)
    for c in inputbuf:
        if c != '\0':
            if in_zero == True:
                zero_count = ord(c)
                zero_count = zero_count -1
                while zero_count>0:

                    newstring = newstring + '\0'
                    zero_count = zero_count -1
                in_zero = False
            else:
                newstring = newstring + c
        else:
            newstring = newstring + c
            in_zero = True
    return newstring[:4]

Alternate implementations for zero_encode and zero_decode in Python 3:

def zero_encode(input: bytes) -> bytes:
    out = ''
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        match _ := input[i]:
            case 0x00:
                # Look ahead from current index.
                # Find next nonzero byte.
                # Use that index as length.
                v = memoryview(input[i:]);
                zeroes = next((x for x, byte in enumerate(v) if byte != 0x00), len(v))
                out += '\0' + chr(zeroes)
                i += zeroes
            case b:
                out += chr(b)
                i += 1
    return bytes(out, encoding='ASCII')

def zero_decode(input: bytes) -> bytes:
    out = ''
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        match _ := input[i]:
            case 0x00:
                out += '\0' * input[i + 1]
                i += 2
            case byte:
                out += chr(byte)
                i += 1
    return bytes(out, encoding='ASCII')