Пример #1
0
 def _split(self, extra_offset):
     """
     Split the body and the extra part.  The extra part must be placed at the
     specified offset, in words. The ptrs in the body will be adjusted
     accordingly.
     """
     body_start = self._get_body_start()
     body_end = self._get_body_end()
     if self._ptrs_size == 0:
         # easy case, just copy the body
         return self._buf.s[body_start:body_end], ''
     #
     # hard case. The layout of self._buf is like this:
     # +----------+------+------+----------+-------------+
     # | garbage0 | data | ptrs | garbage1 |    extra    |
     # +----------+------+------+----------+-------------+
     #                    |   |             ^     ^
     #                    +-----------------+     |
     #                        |                   |
     #                        +-------------------+
     #
     # We recompute the pointers assumining len(garbage1) == extra_offset
     #
     # 1) the data section is copied verbatim
     # 2) the offset of pointers in ptrs are adjusted
     # 3) extra is copied verbatim
     #
     extra_start = self._get_extra_start()
     extra_end = self._get_end()
     #
     # 1) data section
     data_size = self._data_size
     data_buf = self._buf.s[body_start:body_start+data_size*8]
     #
     # 2) ptrs section
     #    for each ptr:
     #        ptr.offset += (extra_offset - old_extra_offset)/8
     #
     # NOTE: ptr.offset is in words, extra_start and body_end in bytes
     old_extra_offset = (extra_start - body_end)/8
     additional_offset = extra_offset - old_extra_offset
     #
     # iterate over and fix the pointers
     parts = [data_buf]
     for j in range(self._ptrs_size):
         # read pointer, update its offset, and pack it
         p = self._read_raw_ptr(j*8)
         if p != 0:
             assert ptr.kind(p) != ptr.FAR
             p = ptr.new_generic(ptr.kind(p),
                                 ptr.offset(p)+additional_offset,
                                 ptr.extra(p))
         s = struct.pack('q', p)
         parts.append(s)
     #
     body_buf = ''.join(parts)
     # 3) extra part
     extra_buf = self._buf.s[extra_start:extra_end]
     #
     return body_buf, extra_buf
Пример #2
0
def test_kind_offset():
    p = 0x0004000200000190
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    #
    p2 = 0x0000064700000101
    assert ptr.kind(p2) == ptr.LIST
Пример #3
0
 def _read_struct(self, offset, structcls):
     """
     Read and dereference a struct pointer at the given offset.  It returns an
     instance of ``structcls`` pointing to the dereferenced struct.
     """
     p = self._read_fast_ptr(offset)
     if ptr.kind(p) == ptr.FAR:
         offset, p = self._read_far_ptr(offset)
     else:
         offset += self._ptrs_offset
     if p == 0:
         return None
     assert ptr.kind(p) == ptr.STRUCT
     obj = structcls.__new__(structcls)
     obj._init_from_pointer(self._seg, offset, p)
     return obj
Пример #4
0
def test_new_far():
    p = ptr.new_far(0, 725, 1)
    assert ptr.kind(p) == ptr.FAR
    assert ptr.far_landing_pad(p) == 0
    assert ptr.far_offset(p) == 725
    assert ptr.far_target(p) == 1
    assert p == 0x00000001000016aa
Пример #5
0
 def _read_list(self, offset, item_type, default_=None):
     p = self._read_fast_ptr(offset)
     if ptr.kind(p) == ptr.FAR:
         offset, p = self._read_far_ptr(offset)
     else:
         offset += self._ptrs_offset
     if p == 0:
         return default_
     assert ptr.kind(p) == ptr.LIST
     list_offset = ptr.deref(p, offset)
     # in theory we could simply use List.from_buffer; however, Cython is
     # not able to compile classmethods, so we create it manually
     obj = List.__new__(List)
     obj._init_from_buffer(self._seg, list_offset, ptr.list_size_tag(p),
                           ptr.list_item_count(p), item_type)
     return obj
Пример #6
0
def test_new_struct():
    p = ptr.new_struct(100, 2, 4)
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    assert ptr.struct_data_size(p) == 2
    assert ptr.struct_ptrs_size(p) == 4
    assert p == 0x0004000200000190
Пример #7
0
def test_new_list():
    p = ptr.new_list(64, 7, 200)
    assert ptr.kind(p) == ptr.LIST
    assert ptr.offset(p) == 64
    assert ptr.list_size_tag(p) == 7
    assert ptr.list_item_count(p) == 200
    assert p == 0x0000064700000101
Пример #8
0
 def visit(self, buf, p, offset):
     kind = ptr.kind(p)
     offset = ptr.deref(p, offset)
     if kind == ptr.STRUCT:
         data_size = ptr.struct_data_size(p)
         ptrs_size = ptr.struct_ptrs_size(p)
         return self.visit_struct(buf, p, offset, data_size, ptrs_size)
     elif kind == ptr.LIST:
         item_size = ptr.list_size_tag(p)
         count = ptr.list_item_count(p)
         if item_size == ptr.LIST_SIZE_COMPOSITE:
             tag = buf.read_ptr(offset)
             count = ptr.offset(tag)
             data_size = ptr.struct_data_size(tag)
             ptrs_size = ptr.struct_ptrs_size(tag)
             return self.visit_list_composite(buf, p, offset,
                                               count, data_size, ptrs_size)
         elif item_size == ptr.LIST_SIZE_PTR:
             return self.visit_list_ptr(buf, p, offset, count)
         elif item_size == ptr.LIST_SIZE_BIT:
             return self.visit_list_bit(buf, p, offset, count)
         else:
             return self.visit_list_primitive(buf, p, offset, item_size, count)
     elif kind == ptr.FAR:
         raise NotImplementedError('Far pointer not supported')
     else:
         assert False, 'unknown ptr kind'
Пример #9
0
 def _hash_str_data(self, offset, default_=hash(None), additional_size=0):
     p = self._read_fast_ptr(offset)
     if ptr.kind(p) == ptr.FAR:
         offset, p = self._read_far_ptr(offset)
     else:
         offset += self._ptrs_offset
     return self._seg.hash_str(p, offset, default_, additional_size)
Пример #10
0
 def hash_str(self, p, offset, default_, additional_size):
     if p == 0:
         return default_
     assert ptr.kind(p) == ptr.LIST
     assert ptr.list_size_tag(p) == ptr.LIST_SIZE_8
     start = ptr.deref(p, offset)
     size = ptr.list_item_count(p) + additional_size
     return _hash.strhash(self.buf, start, size)
Пример #11
0
 def _read_list_or_struct(self, ptr_offset, default_=None):
     ptr_offset, p = self._read_ptr_generic(ptr_offset)
     if p == 0:
         return default_
     blob_offet = ptr.deref(p, ptr_offset)
     if ptr.kind(p) == ptr.STRUCT:
         Struct = capnpy.struct_.Struct
         return Struct.from_buffer(self._buf, blob_offet,
                                   ptr.struct_data_size(p),
                                   ptr.struct_ptrs_size(p))
     elif ptr.kind(p) == ptr.LIST:
         List = capnpy.list.List
         return List.from_buffer(self._buf,
                                 blob_offet, ptr.list_size_tag(p),
                                 ptr.list_item_count(p),
                                 capnpy.list.StructItemType(Blob))
     else:
         assert False, 'Unkwown pointer kind: %s' % ptr.kind(p)
Пример #12
0
def test_struct_ptr():
    #       0004             ptrs size
    #           0002         data size
    #               00000190 offset<<2
    #                      0 kind
    p = 0x0004000200000190
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    assert ptr.struct_data_size(p) == 2
    assert ptr.struct_ptrs_size(p) == 4
Пример #13
0
def test_ListPtr():
    #       0000064          item_count<<1
    #              7         item_size
    #               00000100 offset<<2
    #                      1 kind
    p = 0x0000064700000101
    assert ptr.kind(p) == ptr.LIST
    assert ptr.offset(p) == 64
    assert ptr.list_size_tag(p) == 7
    assert ptr.list_item_count(p) == 200
Пример #14
0
def test_FarPtr():
    #       00000001         target
    #               000016aa offset
    #                      a landing
    #                      a kind
    p = 0x00000001000016aa
    assert ptr.kind(p) == ptr.FAR
    assert ptr.far_landing_pad(p) == 0
    assert ptr.far_offset(p) == 725
    assert ptr.far_target(p) == 1
Пример #15
0
 def read_item(self, lst, i):
     offset = lst._offset + (i * 8)
     p = lst._seg.read_ptr(offset)
     if ptr.kind(p) == ptr.FAR:
         offset, p = lst._seg.read_far_ptr(offset)
     obj = List.__new__(List)
     obj._init_from_buffer(lst._seg, ptr.deref(p, offset),
                           ptr.list_size_tag(p), ptr.list_item_count(p),
                           self.inner_item_type)
     return obj
Пример #16
0
def test__as_pointer():
    buf = b('garbage0'
            '\x01\x00\x00\x00\x00\x00\x00\x00'  # 1
            '\x02\x00\x00\x00\x00\x00\x00\x00') # 2
    b1 = Struct.from_buffer(buf, 8, data_size=2, ptrs_size=0)
    p = b1._as_pointer(24) # arbitrary offset
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.deref(p, 24) == 8
    assert ptr.struct_data_size(p) == 2
    assert ptr.struct_ptrs_size(p) == 0
Пример #17
0
    def ptr(self, offset, s):
        p = struct.unpack('q', s)[0]
        if ptr.kind(p) not in (ptr.STRUCT, ptr.LIST, ptr.FAR):
            return ' ' * 25
        #
        # try to display only "reasonable" ptrs; if the fields are too big, it
        # probably means that the current word is not a pointer
        def if_in_range(x, min, max):
            if min <= x < max:
                return str(x)
            else:
                return '?'

        #
        if p == 0:
            return 'NULL'.ljust(25)
        if ptr.kind(p) == ptr.STRUCT:
            descr = 'struct {:>4} {:>3}'.format(
                if_in_range(ptr.struct_data_size(p), 0, 100),
                if_in_range(ptr.struct_ptrs_size(p), 0, 100))

        elif ptr.kind(p) == ptr.LIST:
            tag = '<%s>' % self._list_tag(ptr.list_size_tag(p))
            descr = 'list{:<5} {:>5}'.format(
                tag, if_in_range(ptr.list_item_count(p), 0, 65536))

        elif ptr.kind(p) == ptr.FAR:
            descr = 'far {:>7} {:>3}'.format(
                ptr.far_landing_pad(p), if_in_range(ptr.far_target(p), 0, 100))
        else:
            descr = 'unknown ptr '
        #
        if -1000 < ptr.offset(p) < 1000:
            dest = ptr.deref(p, offset)
            dest = self.addr(dest)
            dest = dest.ljust(16)
        else:
            dest = '?     '
        line = '{0} to {1}'.format(descr, dest)
        if '?' in line:
            return Color.set(Color.lightgray, line)
        else:
            return line
Пример #18
0
 def read_item(self, lst, i):
     offset = lst._offset + (i * 8)
     p = lst._seg.read_ptr(offset)
     if ptr.kind(p) == ptr.FAR:
         raise NotImplementedError('FAR pointers not supported here')
     obj = List.__new__(List)
     obj._init_from_buffer(lst._seg, ptr.deref(p, offset),
                           ptr.list_size_tag(p), ptr.list_item_count(p),
                           self.inner_item_type)
     return obj
Пример #19
0
 def _get_extra_start(self):
     if self._ptrs_size == 0:
         return self._get_body_end()
     for i in range(self._ptrs_size):
         p = self._read_raw_ptr(i*8)
         assert ptr.kind(p) != ptr.FAR
         if p != 0:
             return self._ptrs_offset + ptr.deref(p, i*8)
     #
     # if we are here, it means that all ptrs are null
     return self._get_body_end()
Пример #20
0
 def _get_extra_start(self):
     if self._ptrs_size == 0:
         return self._get_body_end()
     i = 0
     while i < self._ptrs_size:
         p = self._read_fast_ptr(i * 8)
         assert ptr.kind(p) != ptr.FAR
         if p != 0:
             return self._ptrs_offset + ptr.deref(p, i * 8)
         i += 1
     #
     # if we are here, it means that all ptrs are null
     return self._get_body_end()
Пример #21
0
    def read_str(self, p, offset, default_, additional_size):
        """
        Read Text or Data from the pointer ``p``, which was read from the given
        offset.

        If you want to read a Text, pass additional_size=-1 to remove the
        trailing '\0'. If you want to read a Data, pass additional_size=0.
        """
        if p == 0:
            return default_
        assert ptr.kind(p) == ptr.LIST
        assert ptr.list_size_tag(p) == ptr.LIST_SIZE_8
        start = ptr.deref(p, offset)
        end = start + ptr.list_item_count(p) + additional_size
        return self.buf[start:end]
Пример #22
0
    def read_ptr(self, offset):
        """
        Return the pointer at the specifield offet.

        WARNING: you MUST check if the return value is E_IS_FAR_POINTER, and
        in that case call read_far_ptr. We need this messy interface for
        speed; the proper alternative would be to simply return a tuple
        (offset, p) and handle the far ptr here: this is fine on PyPy but slow
        on CPython, because this way we cannot give a static return type.

        We could raise an exception instead of returning an error value:
        however, this is ~20% slower.
        """
        p = self.read_raw_ptr(offset)
        if ptr.kind(p) == ptr.FAR:
            return ptr.E_IS_FAR_POINTER
        return p
Пример #23
0
def copy_pointer(src, p, src_pos, dst, dst_pos):
    """
    Copy from: BaseSegment src, pointer p living at the src_pos offset
           to: SegmentBuilder dst at position dst_pos
    """
    kind = ptr.kind(p)
    if kind == ptr.STRUCT:
        return _copy_struct(src, p, src_pos, dst, dst_pos)
    elif kind == ptr.LIST:
        item_size = ptr.list_size_tag(p)
        if item_size == ptr.LIST_SIZE_COMPOSITE:
            return _copy_list_composite(src, p, src_pos, dst, dst_pos)
        elif item_size == ptr.LIST_SIZE_PTR:
            return _copy_list_ptr(src, p, src_pos, dst, dst_pos)
        else:
            return _copy_list_primitive(src, p, src_pos, dst, dst_pos)
    elif kind == ptr.FAR:
        src_pos, p = src.read_far_ptr(src_pos)
        return copy_pointer(src, p, src_pos, dst, dst_pos)
Пример #24
0
def copy_pointer(src, p, src_pos, dst, dst_pos):
    """
    Copy from: BaseSegment src, pointer p living at the src_pos offset
           to: SegmentBuilder dst at position dst_pos
    """
    kind = ptr.kind(p)
    if kind == ptr.STRUCT:
        return _copy_struct(src, p, src_pos, dst, dst_pos)
    elif kind == ptr.LIST:
        item_size = ptr.list_size_tag(p)
        if item_size == ptr.LIST_SIZE_COMPOSITE:
            return _copy_list_composite(src, p, src_pos, dst, dst_pos)
        elif item_size == ptr.LIST_SIZE_PTR:
            return _copy_list_ptr(src, p, src_pos, dst, dst_pos)
        else:
            return _copy_list_primitive(src, p, src_pos, dst, dst_pos)
    ## elif kind == ptr.FAR:
    ##     raise NotImplementedError('Far pointer not supported')
    assert False, 'unknown ptr kind: %s' % kind
Пример #25
0
def endof(seg, p, offset):
    """
    Check whether the given object is compact, and in that case compute its
    end boundary. If it's not compact, return -1.

    An object is compact if:

      1. there is no gap between its data section and its ptrs section

      2. there is no gap between children

      3. its children are compact

      4. there are no FAR pointers
    """
    kind = ptr.kind(p)
    offset = ptr.deref(p, offset)
    if kind == ptr.STRUCT:
        data_size = ptr.struct_data_size(p)
        ptrs_size = ptr.struct_ptrs_size(p)
        return _endof_struct(seg, p, offset, data_size, ptrs_size)
    elif kind == ptr.LIST:
        item_size = ptr.list_size_tag(p)
        count = ptr.list_item_count(p)
        if item_size == ptr.LIST_SIZE_COMPOSITE:
            tag = seg.read_ptr(offset)
            count = ptr.offset(tag)
            data_size = ptr.struct_data_size(tag)
            ptrs_size = ptr.struct_ptrs_size(tag)
            return _endof_list_composite(seg, p, offset, count, data_size,
                                         ptrs_size)
        elif item_size == ptr.LIST_SIZE_PTR:
            return _endof_list_ptr(seg, p, offset, count)
        elif item_size == ptr.LIST_SIZE_BIT:
            return _endof_list_bit(seg, p, offset, count)
        else:
            return _endof_list_primitive(seg, p, offset, item_size, count)
    elif kind == ptr.FAR:
        return -1
    else:
        assert False, 'unknown ptr kind'
Пример #26
0
 def read_far_ptr(self, offset):
     """
     Read and return the ptr referenced by this far pointer
     """
     p = self.read_ptr(offset)
     segment_start = self.segment_offsets[ptr.far_target(p)]  # in bytes
     offset = segment_start + ptr.far_offset(p) * 8
     if ptr.far_landing_pad(p) == 0:
         # simple case: the landing pad is a normal pointer, just read it
         p = self.read_ptr(offset)
         return offset, p
     else:
         # complex case. From capnproto specs:
         #     If B == 1, then the "landing pad" is itself another far
         #     pointer that is interpreted differently: This far pointer
         #     (which always has B = 0) points to the start of the object's
         #     content, located in some other segment. The landing pad is
         #     itself immediately followed by a tag word. The tag word
         #     looks exactly like an intra-segment pointer to the target
         #     object would look, except that the offset is always zero.
         #
         # read the 2nd far pointer and the tag word
         p = self.read_ptr(offset)
         ptag = self.read_ptr(offset + 8)
         assert ptr.kind(p) == ptr.FAR
         assert ptr.far_landing_pad(p) == 0
         assert ptr.offset(ptag) == 0
         # compute the absolute offset which the object is located at
         segment_start = self.segment_offsets[ptr.far_target(p)]  # in bytes
         offset = segment_start + ptr.far_offset(p) * 8
         #
         # ptag is a pointer which perfectly describes the object we want
         # to read. Remember that normally when ptr_offset==0, capnproto
         # expects the object to start at offset+8. So here we return
         # offset-8, so that the object will be read at the expected place
         return offset - 8, ptag
Пример #27
0
 def unpack(p):
     assert ptr.kind(p) == ptr.STRUCT
     return ptr.offset(p), ptr.struct_data_size(p), ptr.struct_ptrs_size(p)
Пример #28
0
 def _init_from_pointer(self, buf, offset, p):
     assert ptr.kind(p) == ptr.STRUCT
     struct_offset = ptr.deref(p, offset)
     data_size = ptr.struct_data_size(p)
     ptrs_size = ptr.struct_ptrs_size(p)
     self._init_from_buffer(buf, struct_offset, data_size, ptrs_size)
Пример #29
0
 def unpack(p):
     assert ptr.kind(p) == ptr.FAR
     return ptr.far_landing_pad(p), ptr.far_offset(p), ptr.far_target(p)
Пример #30
0
 def unpack(p):
     assert ptr.kind(p) == ptr.LIST
     return ptr.offset(p), ptr.list_size_tag(p), ptr.list_item_count(p)