'Make a guess to the data type.
Users can provide their own data type guessing code when initializing CFGFast instance, and each guessing
handler will be called if this method fails to determine what the data is.
:param pyvex.IRSB irsb: The pyvex IRSB object.
:param int irsb_addr: Address of the IRSB.
:param int stmt_idx: ID of the statement.
:param int data_addr: Address of the data.
:param int max_size: The maximum size this data entry can be.
:return: a tuple of (data type, size). (None, None) if we fail to determine the type or the size.
:rtype: tuple'

def _guess_data_type(self, irsb, irsb_addr, stmt_idx, data_addr, max_size, content_holder=None):

    if (max_size is None):
        max_size = 0
    if (self._seg_list.is_occupied(data_addr) and (self._seg_list.occupied_by_sort(data_addr) == 'code')):
        return ('code    reference', 0)
    pointer_size = (self.project.arch.bits / 8)
    if isinstance(self.project.loader.main_object, cle.MetaELF):
        plt_entry = self.project.loader.main_object.reverse_plt.get(irsb_addr, None)
        if (plt_entry is not None):
            return ('GOT    PLT    Entry', pointer_size)
    buf = self._fast_memory_load(data_addr)
    if (buf is None):
        return (None, None)
    if (self.project.arch.memory_endness == 'Iend_LE'):
        fmt = '<'
    else:
        fmt = '>'
    if (pointer_size == 8):
        fmt += 'Q'
    elif (pointer_size == 4):
        fmt += 'I'
    else:
        raise AngrCFGError('Pointer    size    of    %d    is    not    supported', pointer_size)
    pointers_count = 0
    max_pointer_array_size = min((512 * pointer_size), max_size)
    for i in xrange(0, max_pointer_array_size, pointer_size):
        ptr_str = self._ffi.unpack(self._ffi.cast('char*', (buf + i)), pointer_size)
        if (len(ptr_str) != pointer_size):
            break
        ptr = struct.unpack(fmt, ptr_str)[0]
        if (ptr is not None):
            if ((self._addr_belongs_to_section(ptr) is not None) or (self._addr_belongs_to_segment(ptr) is not None) or (self._extra_memory_regions and next(((a < ptr < b) for (a, b) in self._extra_memory_regions), None))):
                pointers_count += 1
            else:
                break
    if pointers_count:
        return ('pointer-array', (pointer_size * pointers_count))
    block = self._fast_memory_load(data_addr)
    if ((block[1] == 0) and (block[3] == 0) and (chr(block[0]) in self.PRINTABLES)):
        max_unicode_string_len = 1024
        unicode_str = self._ffi.string(self._ffi.cast('wchar_t*', block), max_unicode_string_len)
        if (len(unicode_str) and all([(c in self.PRINTABLES) for c in unicode_str])):
            if (content_holder is not None):
                content_holder.append(unicode_str)
            return ('unicode', ((len(unicode_str) + 1) * 2))
    max_string_len = min(max_size, 4096)
    s = self._ffi.string(self._ffi.cast('char*', block), max_string_len)
    if len(s):
        if all([(c in self.PRINTABLES) for c in s]):
            if (content_holder is not None):
                content_holder.append(s)
            return ('string', min((len(s) + 1), max_string_len))
    for handler in self._data_type_guessing_handlers:
        (sort, size) = handler(self, irsb, irsb_addr, stmt_idx, data_addr, max_size)
        if (sort is not None):
            return (sort, size)
    return (None, None)
