def _encode_data(entry, value, length): if entry.format in (Field.BINARY, Field.HEX): assert isinstance(value, Data) result = value.copy() elif entry.format == Field.TEXT: assert isinstance(value, basestring) try: result = Data(value.encode(entry.encoding)) except UnicodeDecodeError: raise BadEncodingError(entry, value) elif entry.format == Field.INTEGER: assert isinstance(value, (int, long)) if length is None: raise FieldDataError(entry, "Unable to encode integer field " "without explicit length") assert entry.encoding in [Field.BIG_ENDIAN, Field.LITTLE_ENDIAN] if entry.encoding == Field.BIG_ENDIAN: result = Data.from_int_big_endian(value, length) else: result = Data.from_int_little_endian(value, length) elif entry.format == Field.FLOAT: assert entry.encoding in [Field.BIG_ENDIAN, Field.LITTLE_ENDIAN] assert isinstance(value, float) if entry.encoding == Field.BIG_ENDIAN: result = Data.from_float_big_endian(value, length) else: result = Data.from_float_little_endian(value, length) else: raise Exception("Unknown field format of '%s'!" % entry.format) return result
def convert_value(entry, value, length): """Convert a value to the correct type given the entry. For example, given an integer field, the string '43' would be converted to the number 43.""" temp_original = value if entry.format == Field.BINARY: try: if isinstance(value, Data): value = value.copy() elif isinstance(value, int) or isinstance(value, long): value = Data.from_int_big_endian(value, int(length)) else: value = Data.from_binary_text(_convert_type(entry, value, str)) except DataError, ex: raise FieldDataError(entry, ex)
def _encode_unknown_variable_length_integer(entry, value, params): # Integers require a specific length of encoding. If one is # not specified, we'll try several lengths until we find one # that fits. # # We only consider lengths that are in the range specified by # the entry length to avoid choosing an out of bounds length. assert params is not None, "Asked to encode a variable length field " \ "without parameters. This shouldn't happen." for length in get_valid_integer_lengths(entry, params): try: if entry.format != Field.INTEGER or entry.encoding == Field.BIG_ENDIAN: result = Data.from_int_big_endian(value, length) return result else: return Data.from_int_little_endian(value, length) except IntegerTooLongError: # The value didn't fit in this length... try the next # one. pass else: raise VariableIntegerTooLongError(entry, value)
value = Data('\x00' * (length / 8 + 1), 0, length - len(value)) + value break else: if self.is_hidden: range = EntryValueType(self.entry).range(self._params) value = Ranges([range]).get_default() try: length = self.entry.length.evaluate(context) except UndecodedReferenceError, ex: # We don't know, and can't calculate, the length if value == 0: length = 0 else: length = 8 if self.entry.format in [Field.HEX, Field.BINARY]: value = Data.from_int_big_endian(value, length) elif self.entry.format in [Field.TEXT]: value = '\x00' * (length / 8 - 1) + chr(value) else: # We don't have a default for this entry raise MissingFieldException(self.entry) return value def _get_data(self, value, context): try: length = self.entry.length.evaluate(context) return encode_value(self.entry, value, length) except UndecodedReferenceError, ex: # We don't know how long this entry should be. if self.entry.format == self.entry.INTEGER: return _encode_unknown_variable_length_integer(self.entry, value, self._params)