#!/usr/bin/env python import string, struct from cStringIO import StringIO short_length = 2 ushort_length = 2 long_length = 4 ulong_length = 4 long_long_length = 8 ulong_long_length = 8 float_length = 4 double_length = 8 long_double_length= 16 def padding_length(offset, length): excess = offset % length if excess == 0: return 0 return length - excess def padding(offset, length): return "\0" * padding_length(offset, length) def count(format, octets, offset, byte_order, value): if format == 'b': # boolean return 1 elif format == 'c': # char return 1 elif format == 'C': # wide char # It's difficult to count the size, since the length has already # been emitted raise NotImplementedError elif format == 'o': # octet return 1 elif format == 'h': # short return padding_length(offset, short_length) + short_length elif format == 'H': # unsigned short return padding_length(offset, ushort_length) + ushort_length elif format == 'l': # long return padding_length(offset, long_length) + long_length elif format == 'L': # unsigned long return padding_length(offset, ulong_length) + ulong_length elif format == 'n': # long long return padding_length(offset, long_long_length) + long_long_length elif format == 'N': # unsigned long long return padding_length(offset, ulong_long_length) + ulong_long_length elif format == 'f': # float return padding_length(offset, float_length) + float_length elif format == 'd': # double return padding_length(offset, double_length) + double_length elif format == 'D': # long double return padding_length(offset, double_length) + long_double_length elif format == 's': # string # Determine the number of bytes needed to hold the string size ulong_padding_length = padding_length(offset, ulong_length) string_size_length = ulong_padding_length + ulong_length # Now determine the length of the string string_length = len(value) + 1 # Return the total number of bytes needed for the string return string_size_length + string_length elif format == 'S': # It's difficult to count the size, since the length has already # been emitted raise NotImplementedError elif format == 'O': # sequence of octets # Determine the number of bytes needed to hold the sequence size ulong_padding_length = padding_length(offset, ulong_length) sequence_size_length = ulong_padding_length + ulong_length # Now determine the length of the sequence sequence_length = len(value) # Return the total number of bytes needed for the sequence return sequence_size_length + sequence_length return -1 def marshal(format, octets, offset, byte_order, value): if format == 'b': # boolean octets.write(chr(value)) return offset + 1 if format == 'c': # char octets.write(value) return offset + 1 if format == 'C': # wide char octets.write(value) return offset + len(value) if format == 'o': # octet octets.write(chr(value)) return offset + 1 if format == 'h': # short short_padding_length = padding_length(offset, short_length) octets.write("\0" * short_padding_length) if byte_order == 0: order_fmt = '>h' else: order_fmt = '> 32, value & 0x00000000ffffffffL) else: order_fmt = '> 32) octets.write(str) return offset + long_long_padding_length + long_long_length if format == 'N': # unsigned long long ulong_long_padding_length = padding_length(offset, ulong_long_length) octets.write("\0" * ulong_long_padding_length) if byte_order == 0: order_fmt = '>LL' str = struct.pack(order_fmt, (value & 0xffffffff00000000L) >> 32, value & 0x00000000ffffffffL) else: order_fmt = '> 32) octets.write(str) return offset + ulong_long_padding_length + ulong_long_length if format == 'f': # float float_padding_length = padding_length(offset, float_length) octets.write("\0" * float_padding_length) if byte_order == 0: order_fmt = '>' else: order_fmt = '<' str = struct.pack(order_fmt + 'f', value) octets.write(str) return offset + float_padding_length + float_length if format == 'd': # double double_padding_length = padding_length(offset, double_length) octets.write("\0" * double_padding_length) if byte_order == 0: order_fmt = '>' else: order_fmt = '<' str = struct.pack(order_fmt + 'd', value) octets.write(str) return offset + double_padding_length + double_length if format == 'D': # long double double_padding_length = padding_length(offset, double_length) octets.write("\0" * double_padding_length) if byte_order == 0: octets.write(value.big_endian_bytes()) else: octets.write(value.little_endian_bytes()) return offset + double_padding_length + long_double_length if format == 's': # # string # if byte_order == 0: order_fmt = '>L' else: order_fmt = '> 32) data.append(value & 0x00000000ffffffffL) else: data.append(value & 0x00000000ffffffffL) data.append((value & 0xffffffff00000000L) >> 32) return offset + long_long_padding_length + long_long_length if format == 'N': # unsigned long long long_long_padding_length = padding_length(offset, long_long_length) struct_format.write('x' * long_long_padding_length) struct_format.write('LL') if byte_order == 0: data.append((value & 0xffffffff00000000L) >> 32) data.append(value & 0x00000000ffffffffL) else: data.append(value & 0x00000000ffffffffL) data.append((value & 0xffffffff00000000L) >> 32) return offset + long_long_padding_length + long_long_length if format == 'f': # float float_padding_length = padding_length(offset, float_length) struct_format.write('x' * float_padding_length) struct_format.write('f') data.append(value) return offset + float_padding_length + float_length if format == 'd': # double double_padding_length = padding_length(offset, double_length) struct_format.write('x' * double_padding_length) struct_format.write('d') data.append(value) return offset + double_padding_length + double_length if format == 's': # # string # ulong_padding_length = padding_length(offset, ulong_length) struct_format.write('x' * ulong_padding_length) struct_format.write('L') data.append(len(value)+1) struct_format.write(str(len(value))+'sc') data.append(value) data.append("\0") return offset + ulong_padding_length + ulong_length + len(value) + 1 if format == 'O': # # Sequence of octets # ulong_padding_length = padding_length(offset, ulong_length) struct_format.write('x' * ulong_padding_length) struct_format.write('L') data.append(len(value)) struct_format.write(str(len(value)) + 's') data.append(value) return offset + ulong_padding_length + ulong_length + len(value) return -1 def unmarshal(format, octets, offset, byte_order): if format == 'b': # boolean str = octets.read(1) value = ord(str) return (offset + 1, value) if format == 'c': # char ch = octets.read(1) return (offset + 1, ch) if format == 'C': # wide char; expect length as the parameter length = format[1] value = octets.read(length) return (offset + length, value) if format == 'o': # octet str = octets.read(1) value = ord(str) return (offset + 1, value) if format == 'h': # short short_padding_length = padding_length(offset, short_length) octets.read(short_padding_length) if byte_order == 0: order_fmt = '>h' else: order_fmt = '