Difference between revisions of "Zerocode"

From Second Life Wiki
Jump to navigation Jump to search
(Added a modern alternative.)
(Added sections and full alternative in Python 3.)
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
zero encoding and decoding functions and a couple of useful functions from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399
==Python 3==
This code is a modern implementation of the earlier Python 2 code below.
<syntaxhighlight lang="python">
def encode(input: bytes) -> bytes:
    """
    Zero-bytes are run-length encoded so that up to 255 zeroes become `\\x00\\xff`
    """
    out = bytearray()
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        if (zeroes := (input[i] == 0x00)):
            while (i + zeroes < n) and input[i + zeroes] == 0x00: zeroes += 1
            out.extend([0x00, zeroes])
            i += zeroes
        else:
            out.append(input[i])
            i += 1
    return bytes(out)


def decode(input: bytes) -> bytes:
    """
    Converts bytes where zeroes are run-length encoded,
    such that `\\x00\\xff` is unpacked into 255 `\\x00` bytes.
    """
    out = bytearray()
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        if input[i] == 0x00:
            out.extend(b'\0' * input[i + 1])
            i += 2 # Assumes input was valid.
        else:
            out.append(input[i])
            i += 1
    return bytes(out)
def hex2byte(input: str) -> bytes:
    """
    Converts formatted string `'AA BB CC DD'` into bytes. Spaces are ignored.
    """
    return bytes.fromhex(input.replace(' ',''))
def byte2hex(input: bytes) -> str:
    """
    Converts bytes into formatted string `'AA BB CC DD'`.
    """
    return ' '.join(f'{byte:02X}' for byte in input)
</syntaxhighlight>
==Python 2==
Zero-encoding and decoding functions and a couple of useful functions from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399
This code is used in the [https://wiki.secondlife.com/wiki/Presence_Code_Python Presence Code] example.
<syntaxhighlight lang="python"># From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/510399
<syntaxhighlight lang="python"># 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
Line 108: Line 159:
                  
                  


</syntaxhighlight>
Alternate implementations for <code>zero_encode</code> and <code>zero_decode</code> in Python 3:
<syntaxhighlight lang="python">
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')
</syntaxhighlight>
</syntaxhighlight>
[[Category: AW Groupies]]
[[Category: AW Groupies]]

Latest revision as of 17:17, 10 September 2024

Python 3

This code is a modern implementation of the earlier Python 2 code below.

def encode(input: bytes) -> bytes:
    """
    Zero-bytes are run-length encoded so that up to 255 zeroes become `\\x00\\xff`
    """
    out = bytearray()
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        if (zeroes := (input[i] == 0x00)):
            while (i + zeroes < n) and input[i + zeroes] == 0x00: zeroes += 1
            out.extend([0x00, zeroes])
            i += zeroes
        else:
            out.append(input[i])
            i += 1
    return bytes(out)

def decode(input: bytes) -> bytes:
    """
    Converts bytes where zeroes are run-length encoded,
    such that `\\x00\\xff` is unpacked into 255 `\\x00` bytes.
    """
    out = bytearray()
    i, n = 0, len(input)
    while i < n: # While-loop for index skipping.
        if input[i] == 0x00:
            out.extend(b'\0' * input[i + 1])
            i += 2 # Assumes input was valid.
        else:
            out.append(input[i])
            i += 1
    return bytes(out)

def hex2byte(input: str) -> bytes:
    """
    Converts formatted string `'AA BB CC DD'` into bytes. Spaces are ignored.
    """
    return bytes.fromhex(input.replace(' ',''))

def byte2hex(input: bytes) -> str:
    """
    Converts bytes into formatted string `'AA BB CC DD'`.
    """
    return ' '.join(f'{byte:02X}' for byte in input)

Python 2

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

This code is used in the Presence Code example.

# 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]