Example #1
0
    def overwrite(self, bs, pos=None):
        """Overwrite with bs at bit position pos.

        bs -- The bitstring to overwrite with.
        pos -- The bit position to begin overwriting from.

        Raises ValueError if pos < 0 or pos + bs.len > self.len

        """
        bs = constbitarray.ConstBitArray(bs)
        if not bs.len:
            return
        if pos is None:
            try:
                pos = self._pos
            except AttributeError:
                raise TypeError(
                    "overwrite require a bit position for this type.")
        if pos < 0:
            pos += self.len
        if pos < 0 or pos + bs.len > self.len:
            raise ValueError("Overwrite exceeds boundary of bitstring.")
        self._overwrite(bs, pos)
        try:
            self._pos = pos + bs.len
        except AttributeError:
            pass
Example #2
0
    def prepend(self, bs):
        """Prepend a bitstring to the current bitstring.

        bs -- The bitstring to prepend.

        """
        bs = constbitarray.ConstBitArray(bs)
        self._prepend(bs)
Example #3
0
    def insert(self, bs, pos=None):
        """Insert bs at bit position pos.

        bs -- The bitstring to insert.
        pos -- The bit position to insert at.

        Raises ValueError if pos < 0 or pos > self.len.

        """
        bs = constbitarray.ConstBitArray(bs)
        if not bs.len:
            return self
        if bs is self:
            bs = self.__copy__()
        if pos is None:
            try:
                pos = self._pos
            except AttributeError:
                raise TypeError("insert require a bit position for this type.")
        if pos < 0:
            pos += self.len
        if not 0 <= pos <= self.len:
            raise ValueError("Invalid insert position.")
        self._insert(bs, pos)
Example #4
0
    def replace(self,
                old,
                new,
                start=None,
                end=None,
                count=None,
                bytealigned=None):
        """Replace all occurrences of old with new in place.

        Returns number of replacements made.

        old -- The bitstring to replace.
        new -- The replacement bitstring.
        start -- Any occurrences that start before this will not be replaced.
                 Defaults to 0.
        end -- Any occurrences that finish after this will not be replaced.
               Defaults to self.len.
        count -- The maximum number of replacements to make. Defaults to
                 replace all occurrences.
        bytealigned -- If True replacements will only be made on byte
                       boundaries.

        Raises ValueError if old is empty or if start or end are
        out of range.

        """
        old = constbitarray.ConstBitArray(old)
        new = constbitarray.ConstBitArray(new)
        if not old.len:
            raise ValueError("Empty bitstring cannot be replaced.")
        start, end = self._validate_slice(start, end)
        if bytealigned is None:
            bytealigned = bitstring.bytealigned
        # Adjust count for use in split()
        if count is not None:
            count += 1
        sections = self.split(old, start, end, count, bytealigned)
        lengths = [s.len for s in sections]
        if len(lengths) == 1:
            # Didn't find anything to replace.
            return 0  # no replacements done
        if new is self:
            # Prevent self assignment woes
            new = copy.copy(self)
        positions = [lengths[0] + start]
        for l in lengths[1:-1]:
            # Next position is the previous one plus the length of the next section.
            positions.append(positions[-1] + l)
        # We have all the positions that need replacements. We do them
        # in reverse order so that they won't move around as we replace.
        positions.reverse()
        try:
            # Need to calculate new pos, if this is a bitstream
            newpos = self._pos
            for p in positions:
                self[p:p + old.len] = new
            if old.len != new.len:
                diff = new.len - old.len
                for p in positions:
                    if p >= newpos:
                        continue
                    if p + old.len <= newpos:
                        newpos += diff
                    else:
                        newpos = p
            self._pos = newpos
        except AttributeError:
            for p in positions:
                self[p:p + old.len] = new
        assert self._assertsanity()
        return len(lengths) - 1
Example #5
0
 def __ixor__(self, bs):
     bs = constbitarray.ConstBitArray(bs)
     if self.len != bs.len:
         raise ValueError("Bitstrings must have the same length "
                          "for ^= operator.")
     return self._ixor(bs)
Example #6
0
    def __setitem__(self, key, value):
        """Set item or range to new value.

        Indices are in units of the step parameter (default 1 bit).
        Stepping is used to specify the number of bits in each item.

        If the length of the bitstring is changed then pos will be moved
        to after the inserted section, otherwise it will remain unchanged.

        >>> s = BitArray('0xff')
        >>> s[0:1:4] = '0xe'
        >>> print s
        '0xef'
        >>> s[4:4] = '0x00'
        >>> print s
        '0xe00f'

        """
        try:
            # A slice
            start, step = 0, 1
            if key.step is not None:
                step = key.step
        except AttributeError:
            # single element
            if key < 0:
                key += self.len
            if not 0 <= key < self.len:
                raise IndexError("Slice index out of range.")
            if isinstance(value, numbers.Integral):
                if not value:
                    self._unset(key)
                    return
                if value in (1, -1):
                    self._set(key)
                    return
                raise ValueError(
                    "Cannot set a single bit with integer {0}.".format(value))
            value = constbitarray.ConstBitArray(value)
            if value.len == 1:
                # TODO: this can't be optimal
                if value[0]:
                    self._set(key)
                else:
                    self._unset(key)
            else:
                self._delete(1, key)
                self._insert(value, key)
            return
        else:
            # If value is an integer then we want to set the slice to that
            # value rather than initialise a new bitstring of that length.
            if not isinstance(value, numbers.Integral):
                try:
                    value = constbitarray.ConstBitArray(value)
                except TypeError:
                    raise TypeError("Bitstring, integer or string expected. "
                                    "Got {0}.".format(type(value)))
            if not step:
                stop = 0
            else:
                # default stop needs to be a multiple of step
                stop = self.len
                if key.stop is not None:
                    stop -= (self.len % abs(step))
            if key.start is not None:
                start = key.start * abs(step)
                if key.start < 0:
                    start += stop
                if start < 0:
                    start = 0
            if key.stop is not None:
                stop = key.stop * abs(step)
                if key.stop < 0:
                    stop += self.len - (self.len % abs(step))
            # Adjust start and stop if we're stepping backwards
            if step < 0:
                if key.start is None:
                    start = self.len + step
                if key.stop is None:
                    stop = step
                start, stop = stop - step, start - step
            if start > stop:
                if step == 1:
                    # The standard behaviour for lists is to just insert at the
                    # start position if stop < start and step == 1.
                    stop = start
                else:
                    # We have a step which takes us in the wrong direction,
                    # and will never get from start to stop.
                    raise ValueError("Attempt to assign to badly defined "
                                     "extended slice.")
            if isinstance(value, numbers.Integral):
                if value >= 0:
                    value = self.__class__(uint=value, length=stop - start)
                else:
                    value = self.__class__(int=value, length=stop - start)
            stop = min(stop, self.len)
            start = max(start, 0)
            start = min(start, stop)
            if (stop - start) == value.len:
                if not value.len:
                    return
                if step >= 0:
                    self._overwrite(value, start)
                else:
                    self._overwrite(value.__getitem__(slice(None, None, step)),
                                    start)
            else:
                # TODO: A delete then insert is wasteful - it could do unneeded shifts.
                # Could be either overwrite + insert or overwrite + delete.
                self._delete(stop - start, start)
                if step >= 0:
                    self._insert(value, start)
                else:
                    self._insert(value.__getitem__(slice(None, None, step)),
                                 start)
                # pos is now after the inserted piece.
            return