Ejemplo n.º 1
0
def ConvTypeToStr(t):
  """Gets a string name and size information for a type.

  Args:
    t: The type object.

  Returns:
    (name, length, dimensions):
      name: String name of the type.
      length: Number of elements in the type (1 if not an array).
      dim: Number of dimensions of the type.

  Raises:
    ValueError: The provided type is not recognized.
  """
  cc_str, ul_str = ConvTypeToStrHelper(t)
  if use_underlines:
    cc_str = ul_str
  if cc_str is not None:
    return cc_str, 1, 0
  elif isinstance(t, type(ctypes.Structure)):
    if t._typedef_:
      return autogen_util.CStructName(t), 1, 0
    else:
      return 'struct ' + autogen_util.CStructName(t), 1, 0
  elif isinstance(t, type(ctypes.Array)):
    s, l, dim = ConvTypeToStr(t()._type_)
    return s, len(t()) * l, dim + 1

  raise ValueError('Unknown type: %s' % t)
Ejemplo n.º 2
0
def Pack(message):
  """Return a packed representation of the message.

  Args:
    message: Message to unpack.

  Returns:
    Byte array (as c_ubyte_Array_N, where N is the packed size) containing the
    packed message. Returns None if packing was unsuccessful.
  """

  # TODO: Make AioClient selective about sending raw bytes, and then
  # make Pack() raise an exception if the message doesn't live in a pack module.
  pack_module = _GetPackModule(type(message).__module__)
  if not pack_module:
    return

  class_name = autogen_util.CStructName(type(message))
  try:
    pack_class = getattr(pack_module, class_name)
    pack_function = getattr(pack_module, 'Pack' + class_name)
    pack_size = getattr(pack_module, 'PACK_' + class_name.upper() + '_SIZE')
  except AttributeError:
    return

  # The pack function expects a reference to the message type defined in its own
  # module. This constructs an appropriate object using the same memory
  # underlying the original message.
  if not isinstance(message, pack_class):
    message = pack_class.from_buffer(message)

  packed = (ctypes.c_uint8 * pack_size)()
  assert pack_function(ctypes.byref(message), 1, packed)
  return packed
Ejemplo n.º 3
0
def _GetTypeInfo(t):
    """Return information about a type.

  Args:
    t: A type.

  Returns:
    A tuple of three elements.  The first element is the type name,
    the second entry is a string for the type of pointer that
    represents this object (e.g. "double" for both Array1D_double and
    Array2D_double and "char" for String), and the third element is a
    list of dimensions indicating the length of strings and arrays.

  Raises:
    TypeError: A type was passed in which this function cannot handle.
  """
    ctype_to_str_dict = {
        ctypes.c_bool: ('Boolean', 'bool'),
        ctypes.c_double: ('Double', 'double'),
        ctypes.c_float: ('Float', 'float'),
        ctypes.c_int8: ('Int8', 'int8_t'),
        ctypes.c_int16: ('Int16', 'int16_t'),
        ctypes.c_int32: ('Int32', 'int32_t'),
        ctypes.c_int64: ('Int64', 'int64_t'),
        ctypes.c_uint8: ('UInt8', 'uint8_t'),
        ctypes.c_uint16: ('UInt16', 'uint16_t'),
        ctypes.c_uint32: ('UInt32', 'uint32_t'),
        ctypes.c_uint64: ('UInt64', 'uint64_t'),
    }

    if _IsStringType(t):
        return ('String', 'char', [_ArrayCTypeLength(t)])
    elif _IsArrayType(t):
        (scalar_type, dim) = _GetArrayTypeInfo(t)
        (scalar_type_name, scalar_ptr_name,
         scalar_dim) = _GetTypeInfo(scalar_type)
        return ('Array%dD_%s' % (len(dim), scalar_type_name), scalar_ptr_name,
                dim + scalar_dim)
    elif _IsStructType(t):
        return ('Struct_' + autogen_util.CStructName(t),
                autogen_util.CStructName(t), [])
    elif _IsFundamentalType(t) and t in ctype_to_str_dict:
        names = ctype_to_str_dict[t]
        return (names[0], names[1], [])
    else:
        raise TypeError('Unknown type: %s.' % str(t))
Ejemplo n.º 4
0
def PackSize(message_type):
  pack_module = _GetPackModule(message_type.__module__)
  if not pack_module:
    return

  class_name = autogen_util.CStructName(message_type)
  try:
    return getattr(pack_module, 'PACK_' + class_name.upper() + '_SIZE')
  except AttributeError:
    return
Ejemplo n.º 5
0
def Unpack(packed, message_type):
  """Unpack a packed message.

  Args:
    packed: Packed message data in a (ctypes.c_uint8 * N), where N is the pack
       size, or a string of the same length.
    message_type: Class of the unpacked message.

  Returns:
    An instance of type `message_type` populated with the packed data, or
    None if the unpacking was unsuccessful.

  Raises:
    UnpackError: `packed` is of the wrong type.
  """

  pack_module = _GetPackModule(message_type.__module__)
  if not pack_module:
    return

  class_name = autogen_util.CStructName(message_type)
  try:
    pack_class = getattr(pack_module, class_name)
    unpack_function = getattr(pack_module, 'Unpack' + class_name)
    pack_size = getattr(pack_module, 'PACK_' + class_name.upper() + '_SIZE')
  except AttributeError:
    return

  buffer_type = ctypes.c_uint8 * pack_size
  if isinstance(packed, str) and len(packed) == pack_size:
    packed = buffer_type.from_buffer_copy(packed)
  if not isinstance(packed, buffer_type):
    raise UnpackError('Packed message must be of type %s or a string of the '
                      'same length. Actual type is %s.' %
                      (buffer_type.__name__, type(packed)))

  # The pack function expects a reference to the message type defined in its own
  # module.
  message = pack_class()
  assert unpack_function(packed, 1, ctypes.byref(message)) == pack_size
  if pack_class() != message_type:
    message = message_type.from_buffer(message)
  return message
Ejemplo n.º 6
0
def GatherStructs(header, xml_file, python_file):
  """Returns Python structures necessary to build structs in header file.

  Args:
    header: Path to header file.
    xml_file: Path to XML file.
    python_file: Path to Python file.

  Returns:
    3-tuple consisting of:
      parent_structs: Top-level structs needing pack functions.
      child_structs: Structs on which parent_structs depend.
      child_ctypes: ctype classes for child_structs.
  """
  def IsTypedefStruct(t):
    """Tells whether the struct is typedef'd.

    E.g. typedef struct {} a; versus struct a {};

    Args:
      t: The struct translated from C.

    Returns:
      True if the struct is typedef'ed.
    """
    return t.__name__.startswith('struct_')

  def RootTypeElmt(type_id, by_id):
    """Find the element that defines the base type.

    The root type is one that is not derived as a typedef or array.

    Args:
      type_id: ID of the XML Dom that defines a type.
      by_id: <key, value> dictionary of XML Dom ID and the Dom element.

    Returns:
      The XML Dom element that defines the root type.
    """
    while True:
      if type_id is None or type_id not in by_id:
        return None
      elmt = by_id[type_id]
      if elmt.tag == 'Typedef':
        type_id = elmt.attrib.get('type', None)
      elif elmt.tag == 'ArrayType':
        type_id = elmt.attrib.get('type', None)
      else:
        return elmt

  global use_underlines  # pylint: disable=W0603
  xml_elmts = ElementTree.parse(xml_file).getroot()
  file_ids = [elmt.attrib['id'] for elmt in xml_elmts
              if (elmt.tag == 'File'
                  and os.path.realpath(elmt.attrib['name']).endswith(header))]
  assert len(file_ids) == 1
  local_structs = {elmt.attrib['id']: elmt for elmt in xml_elmts
                   if (elmt.tag == 'Struct'
                       and elmt.attrib['file'] == file_ids[0])}
  by_id = {elmt.attrib['id']: elmt for elmt in xml_elmts
           if elmt.attrib.get('id', None)}
  all_structs = {elmt.attrib['id']: elmt for elmt in xml_elmts
                 if elmt.tag == 'Struct'}

  struct_names = collections.defaultdict(list)
  # The same struct can have multiple names.
  sid_by_name = {}

  for sid, elmt in all_structs.iteritems():
    if elmt.attrib.get('name', None):
      struct_names[sid].append(elmt.attrib['name'])
      sid_by_name[elmt.attrib['name']] = sid

  typedef_structs = []
  for root_id, elmt in by_id.iteritems():
    if elmt.tag == 'Typedef':
      name = elmt.attrib['name']
      child_id = root_id
      while child_id in by_id and by_id[child_id].tag == 'Typedef':
        child_id = by_id[child_id].attrib['type']
      if child_id in by_id and by_id[child_id].tag == 'Struct':
        typedef_structs.append(name)
        struct_names[child_id].append(name)
        sid_by_name[name] = child_id

  if all([not IsCamelCase(s) for s in typedef_structs] +
         [not IsCamelCase(s.attrib['name']) for s in local_structs.itervalues()
          if s.attrib.get('name', None)]):
    use_underlines = True

  mod = imp.load_source('tmp', python_file)
  child_strs = []
  ctype_strs = []
  for sid in local_structs.iterkeys():
    s = struct_names[sid][0]
    slst, clst = FindChildTypes(getattr(mod, s))
    child_strs += slst
    ctype_strs += clst
  parent_structs = set([
      getattr(mod, struct_names[sid][0]) for sid in local_structs.iterkeys()])
  child_structs = set([getattr(mod, s) for s in child_strs])
  child_structs.difference_update(parent_structs)
  child_ctypes = set([getattr(ctypes, s) for s in ctype_strs])

  # Sort lists to generate exactly the same code for each execution.
  child_ctypes = sorted(child_ctypes, key=str)

  # Adds a _typedef_ field that records whether the struct is a
  # typedef'd struct or not.  (e.g. typedef struct {} a; versus
  # struct a {};)
  for s in parent_structs | child_structs:
    s._typedef_ = IsTypedefStruct(s)

  # Add struct typedefs as an _aliases_ field.
  for s in parent_structs | child_structs:
    for typedef in typedef_structs:
      if not getattr(mod, typedef, None):
        continue
      if s == getattr(mod, typedef) and typedef != s.__name__:
        if not hasattr(s, '_aliases_'):
          s._aliases_ = []
        s._aliases_.append(typedef)

  for s in parent_structs | child_structs:
    if hasattr(s, '_aliases_'):
      s._aliases_.sort()

  # Add an _enums_ field to list fields in a struct which are enums.
  enum_types = set()
  for s in parent_structs | child_structs:
    s._enums_ = {}
    struct_name = autogen_util.CStructName(s)
    if struct_name not in sid_by_name:
      continue

    for field_id in all_structs[
        sid_by_name[struct_name]].attrib['members'].split():
      if field_id in by_id and by_id[field_id].tag == 'Field':
        name = by_id[field_id].attrib['name']
        base_type = RootTypeElmt(by_id[field_id].attrib['type'], by_id)
        if base_type.tag == 'Enumeration':
          enum_type = base_type.attrib['name']
          s._enums_[name] = enum_type
          enum_types.add(enum_type)

  # Sort the returned lists in a deterministic order for a definite CRC.
  enum_types = sorted(enum_types)
  return parent_structs, child_structs, child_ctypes, enum_types
Ejemplo n.º 7
0
def WriteDefinePackedSize(f, s, name=None):
  if not name:
    name = autogen_util.CStructName(s)
  size = GetTypePackedSize(s)
  f.write('\n#define PACK_%s_SIZE %d'
          % (str.upper(name), size))