def _GetCppWrapperType(self, kind, add_same_module_namespaces=False): def _AddOptional(type_name): return "base::Optional<%s>" % type_name if self._IsTypemappedKind(kind): type_name = self._GetNativeTypeName(kind) if (mojom.IsNullableKind(kind) and not self.typemap[self._GetFullMojomNameForKind( kind)]["nullable_is_same_type"]): type_name = _AddOptional(type_name) return type_name if mojom.IsEnumKind(kind): return self._GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): return "%sPtr" % self._GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsArrayKind(kind): pattern = "WTF::Vector<%s>" if self.for_blink else "std::vector<%s>" if mojom.IsNullableKind(kind): pattern = _AddOptional(pattern) return pattern % self._GetCppWrapperType( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsMapKind(kind): pattern = ("WTF::HashMap<%s, %s>" if self.for_blink else "base::flat_map<%s, %s>") if mojom.IsNullableKind(kind): pattern = _AddOptional(pattern) return pattern % ( self._GetCppWrapperType( kind.key_kind, add_same_module_namespaces=add_same_module_namespaces), self._GetCppWrapperType( kind.value_kind, add_same_module_namespaces=add_same_module_namespaces)) if mojom.IsInterfaceKind(kind): return "%sPtrInfo" % self._GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsInterfaceRequestKind(kind): return "%sRequest" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsPendingRemoteKind(kind): return "mojo::PendingRemote<%s>" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsPendingReceiverKind(kind): return "mojo::PendingReceiver<%s>" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsPendingAssociatedRemoteKind(kind): return "mojo::PendingAssociatedRemote<%s>" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsPendingAssociatedReceiverKind(kind): return "mojo::PendingAssociatedReceiver<%s>" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsAssociatedInterfaceKind(kind): return "%sAssociatedPtrInfo" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsAssociatedInterfaceRequestKind(kind): return "%sAssociatedRequest" % self._GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsStringKind(kind): if self.for_blink: return "WTF::String" type_name = "std::string" return (_AddOptional(type_name) if mojom.IsNullableKind(kind) else type_name) if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): return "mojo::ScopedDataPipeConsumerHandle" if mojom.IsDataPipeProducerKind(kind): return "mojo::ScopedDataPipeProducerHandle" if mojom.IsMessagePipeKind(kind): return "mojo::ScopedMessagePipeHandle" if mojom.IsSharedBufferKind(kind): return "mojo::ScopedSharedBufferHandle" if mojom.IsPlatformHandleKind(kind): return "mojo::PlatformHandle" if not kind in _kind_to_cpp_type: raise Exception("Unrecognized kind %s" % kind.spec) return _kind_to_cpp_type[kind]
def IsEnumField(field): return mojom.IsEnumKind(field.kind)
def ShouldPassParamByValue(kind): if IsTypemappedKind(kind): if mojom.IsEnumKind(kind): return True return _current_typemap[GetFullMojomNameForKind(kind)]["pass_by_value"] return not mojom.IsStringKind(kind)
def IsNativeOnlyKind(kind): return (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)) and \ kind.native_only
def IsEnumArrayKind(kind): return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind)
def TranslateConstants(token, kind): if isinstance(token, mojom.NamedValue): # Both variable and enum constants are constructed like: # Namespace::Struct::CONSTANT_NAME # For enums, CONSTANT_NAME is ENUM_NAME_ENUM_VALUE. name = [] if token.imported_from: name.extend(NamespaceToArray(token.namespace)) if token.parent_kind: name.append(token.parent_kind.name) if IsEnumToken(token): name.extend([token.enum.name, token.name]) else: name.append(token.name) ret = "::".join(name) # Explicitly disallow cases where we are translating an enum token for a # non-enum (but defined) kind. if IsEnumToken( token) and kind is not None and not mojom.IsEnumKind(kind): raise Exception( "Assignment of enum value '%s' to type %s is disallowed" % (ret, _kind_to_cpp_type.get(kind, "<unknown>"))) # Explicitly disallow a non-enum token for an enum kind, we need an explicit # cast. if not IsEnumToken(token) and mojom.IsEnumKind(kind): raise Exception( "Assignment of non-enum value '%s' to enum-type %s is disallowed" % (ret, GetNameForKind(kind))) return ret if isinstance(token, mojom.BuiltinValue): if token.value == "double.INFINITY" or token.value == "float.INFINITY": return "INFINITY" if token.value == "double.NEGATIVE_INFINITY" or \ token.value == "float.NEGATIVE_INFINITY": return "-INFINITY" if token.value == "double.NAN" or token.value == "float.NAN": return "NAN" if (kind is not None and mojom.IsFloatKind(kind)): return token if token.isdigit() else token + "f" # Per C++11, 2.14.2, the type of an integer literal is the first of the # corresponding list in Table 6 in which its value can be represented. In this # case, the list for decimal constants with no suffix is: # int, long int, long long int # The standard considers a program ill-formed if it contains an integer # literal that cannot be represented by any of the allowed types. # # As it turns out, MSVC doesn't bother trying to fall back to long long int, # so the integral constant -2147483648 causes it grief: it decides to # represent 2147483648 as an unsigned integer, and then warns that the unary # minus operator doesn't make sense on unsigned types. Doh! if kind == mojom.INT32 and token == "-2147483648": return "(-%d - 1) /* %s */" % ( 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618") ret = "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, "")) # Literal tokens may not be assigned to enum variable. By definition, the # only valid tokens for the RHS of an assignment to an enum named values # (specifically, members of the enumeration). if mojom.IsEnumKind(kind): raise Exception( "Assignment of literal '%s' to enum-type %s is disallowed" % (ret, GetNameForKind(kind))) return ret
def IsMojoType(kind): return mojom.IsEnumKind(kind)
def GetCppWrapperType(kind, add_same_module_namespaces=False): def _AddOptional(type_name): pattern = "WTF::Optional<%s>" if _for_blink else "base::Optional<%s>" return pattern % type_name if IsTypemappedKind(kind): type_name = GetNativeTypeName(kind) if (mojom.IsNullableKind(kind) and not _current_typemap[GetFullMojomNameForKind(kind)][ "nullable_is_same_type"]): type_name = _AddOptional(type_name) return type_name if mojom.IsEnumKind(kind): return GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): return "%sPtr" % GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsArrayKind(kind): pattern = None if _use_new_wrapper_types: pattern = "WTF::Vector<%s>" if _for_blink else "std::vector<%s>" if mojom.IsNullableKind(kind): pattern = _AddOptional(pattern) else: pattern = "mojo::WTFArray<%s>" if _for_blink else "mojo::Array<%s>" return pattern % GetCppWrapperType( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsMapKind(kind): pattern = None if _use_new_wrapper_types: pattern = ("WTF::HashMap<%s, %s>" if _for_blink else "std::unordered_map<%s, %s>") if mojom.IsNullableKind(kind): pattern = _AddOptional(pattern) else: pattern = "mojo::WTFMap<%s, %s>" if _for_blink else "mojo::Map<%s, %s>" return pattern % ( GetCppWrapperType( kind.key_kind, add_same_module_namespaces=add_same_module_namespaces), GetCppWrapperType( kind.value_kind, add_same_module_namespaces=add_same_module_namespaces)) if mojom.IsInterfaceKind(kind): return "%sPtr" % GetNameForKind( kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsInterfaceRequestKind(kind): return "%sRequest" % GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsAssociatedInterfaceKind(kind): return "%sAssociatedPtrInfo" % GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsAssociatedInterfaceRequestKind(kind): return "%sAssociatedRequest" % GetNameForKind( kind.kind, add_same_module_namespaces=add_same_module_namespaces) if mojom.IsStringKind(kind): if _for_blink: return "WTF::String" if not _use_new_wrapper_types: return "mojo::String" type_name = "std::string" return _AddOptional(type_name) if mojom.IsNullableKind(kind) else type_name if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): return "mojo::ScopedDataPipeConsumerHandle" if mojom.IsDataPipeProducerKind(kind): return "mojo::ScopedDataPipeProducerHandle" if mojom.IsMessagePipeKind(kind): return "mojo::ScopedMessagePipeHandle" if mojom.IsSharedBufferKind(kind): return "mojo::ScopedSharedBufferHandle" if not kind in _kind_to_cpp_type: raise Exception("Unrecognized kind %s" % kind.spec) return _kind_to_cpp_type[kind]
def _CppToObjCAssign(self, field, obj): kind = field.kind accessor = "%s.%s" % (obj, field.name) if self._IsObjCNumberKind(kind): return accessor if self._IsMojomStruct(kind): args = (self.class_prefix, kind.name, kind.name, accessor) base = "[[%s%s alloc] initWith%s:*%s]" % args if mojom.IsNullableKind(kind): return """^%s%s *{ if (%s.get() != nullptr) { return %s; } return nil; }()""" % (self.class_prefix, kind.name, accessor, base) else: return base if mojom.IsEnumKind(kind): return "static_cast<%s%s>(%s)" % (self.class_prefix, kind.name, accessor) if mojom.IsStringKind(kind): return "[NSString stringWithUTF8String:%s.c_str()]" % accessor if mojom.IsArrayKind(kind): # Only currently supporting: `[string]`, `[number]`, and `[struct]` array_kind = kind.kind if mojom.IsStringKind(array_kind) or self._IsObjCNumberKind( array_kind): return "NSArrayFromVector(%s)" % accessor elif self._IsMojomStruct(array_kind): # Mojo IDL array<struct> actually creates a # `std::vector<mojom::StructPtr<struct>>``, instead of just a plain # vector of `struct`, which needs to be handled appropriately as # `StructPtr` does not allow copy and assign, and acts like a unique_ptr return """^{ const auto a = [NSMutableArray new]; for (const auto& o : %s) { [a addObject:%s]; } return a; }()""" % (accessor, self._CppPtrToObjCTransform(array_kind, 'o')) else: raise Exception("Unsupported array kind %s" % array_kind.spec) if mojom.IsMapKind(kind): # Only currently supporting: `{string: string}`, `{string: number}`, and # `{string: struct}` key_kind = kind.key_kind val_kind = kind.value_kind if mojom.IsStringKind(key_kind): if mojom.IsStringKind(val_kind) or self._IsObjCNumberKind( val_kind): return "NSDictionaryFromMap(%s)" % accessor elif self._IsMojomStruct(val_kind): # Mojo IDL map<*, struct> actually creates a # `base::flat_map<*, mojom::StructPtr<struct>>``, instead of just a # plain std::map of `struct`, which needs to be handled appropriately # as `StructPtr` does not allow copy and assign, and acts like a # unique_ptr return """^{ const auto d = [NSMutableDictionary new]; for (const auto& item : %s) { d[[NSString stringWithUTF8String:item.first.c_str()]] = %s; } return d; }()""" % (accessor, self._CppPtrToObjCTransform(val_kind, 'item.second')) else: raise Exception("Unsupported dictionary value kind %s" % val_kind.spec) else: raise Exception("Unsupported dictionary key kind %s" % key_kind.spec) return "%s" % accessor
def _WriteInputParamForTracingImpl(generator, kind, cpp_parameter_name, output_context): """Generates lines of C++ to log a parameter into TracedValue |output_context.value|. Use |output_context.name| if |output_context| is of inhereted type from _OutputContext. Args: kind: {Kind} The kind of the parameter (corresponds to its C++ type). cpp_parameter_name: {string} The actual C++ variable name corresponding to the mojom parameter |parameter_name|. Can be a valid C++ expression (e.g., dereferenced variable |"(*var)"|). output_context: {_OutputContext} Represents the TracedValue* variable to be written into. Possibly also holds the mojo parameter name corresponding to |cpp_parameter_name|. Yields: {string} C++ lines of code that trace a |cpp_parameter_name| into |output_context.value|. """ def _WrapIfNullable(inner_lines): """Check if kind is nullable if so yield code to check whether it has value. Args: inner_lines: {function} Function taking single argument and returning iterable. If kind is nullable, yield from this method with |cpp_parameter_name+'.value()'| otherwise yield with the parameter |cpp_parameter_name|. Args from the surrounding method: kind cpp_parameter_name output_context.AddSingleValue """ if mojom.IsNullableKind(kind): yield 'if (%s.has_value()) {' % cpp_parameter_name for line in inner_lines(cpp_parameter_name + '.value()'): yield ' ' + line yield '} else {' yield ' ' + output_context.AddSingleValue('String', '"base::nullopt"') yield '}' else: # |yield from| is introduced in Python3.3. for line in inner_lines(cpp_parameter_name): yield line # TODO(crbug.com/1103623): Support more involved types. if mojom.IsEnumKind(kind): if generator._IsTypemappedKind(kind) or IsNativeOnlyKind(kind): yield output_context.AddSingleValue( 'Integer', 'static_cast<int>(%s)' % cpp_parameter_name) else: yield output_context.AddSingleValue( 'String', 'base::trace_event::ValueToString(%s)' % cpp_parameter_name) return if mojom.IsStringKind(kind): if generator.for_blink: # WTF::String is nullable on its own. yield output_context.AddSingleValue('String', '%s.Utf8()' % cpp_parameter_name) return # The type might be base::Optional<std::string> or std::string. for line in _WrapIfNullable(lambda cpp_parameter_name: [ output_context.AddSingleValue('String', cpp_parameter_name) ]): yield line return if kind == mojom.BOOL: yield output_context.AddSingleValue('Boolean', cpp_parameter_name) return # TODO(crbug.com/1103623): Make TracedValue support int64_t, then move to # mojom.IsIntegralKind. if kind in [mojom.INT8, mojom.UINT8, mojom.INT16, mojom.UINT16, mojom.INT32]: # Parameter is representable as 32bit int. yield output_context.AddSingleValue('Integer', cpp_parameter_name) return if kind in [mojom.UINT32, mojom.INT64, mojom.UINT64]: yield output_context.AddSingleValue( 'String', 'base::NumberToString(%s)' % cpp_parameter_name) return if mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind): yield output_context.AddSingleValue('Double', cpp_parameter_name) return if (mojom.IsStructKind(kind) and not generator._IsTypemappedKind(kind) and not IsNativeOnlyKind(kind)): yield 'if (%s.is_null()) {' % cpp_parameter_name yield ' ' + output_context.AddSingleValue('String', '"nullptr"') yield '} else {' yield ' ' + output_context.BeginContainer('Dictionary') yield ' ' + output_context.AsValueInto(cpp_parameter_name) yield ' ' + output_context.EndContainer('Dictionary') yield '}' return if mojom.IsArrayKind(kind): iterator_name = 'item' loop_body = _WriteInputParamForTracingImpl(generator=generator, kind=kind.kind, cpp_parameter_name=iterator_name, output_context=_ArrayItem( output_context.value)) loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( container_type='Array', iterator_name=iterator_name, container_name=cpp_parameter_name, loop_body=loop_body) # Array might be a nullable kind. for line in _WrapIfNullable(loop_generator): yield line return def _TraceEventToString(cpp_parameter_name=cpp_parameter_name, kind=kind): return 'base::trace_event::ValueToString(%s, "<value of type %s>")' % ( cpp_parameter_name, generator._GetCppWrapperParamType(kind)) if mojom.IsMapKind(kind): iterator_name = 'item' if generator.for_blink: # WTF::HashMap<,> key_access = '.key' value_access = '.value' else: # base::flat_map<,> key_access = '.first' value_access = '.second' loop_body = _WriteInputParamForTracingImpl( generator=generator, kind=kind.value_kind, cpp_parameter_name=iterator_name + value_access, output_context=_DictionaryItemWithCopiedKey( value=output_context.value, name=_TraceEventToString(cpp_parameter_name=iterator_name + key_access, kind=kind.key_kind))) loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( container_type="Dictionary", iterator_name=iterator_name, container_name=cpp_parameter_name, loop_body=loop_body) # Dictionary might be a nullable kind. for line in _WrapIfNullable(loop_generator): yield line return yield output_context.AddSingleValue('String', _TraceEventToString())
def _ObjCToCppAssign(self, field, obj): kind = field.kind accessor = "%s.%s" % (obj, self._ObjCPropertyFormatter(field.name)) if self._IsObjCNumberKind(kind): return accessor if self._IsMojomStruct(kind): if mojom.IsNullableKind(kind): return "%s != nil ? %s.cppObjPtr : nullptr" % (accessor, accessor) else: return "%s.cppObjPtr" % accessor if mojom.IsEnumKind(kind): return "static_cast<%s::%s>(%s)" % (self._CppNamespace(), kind.name, accessor) if mojom.IsStringKind(kind): return "%s.UTF8String" % accessor if mojom.IsArrayKind(kind): # Only currently supporting: `[string]`, `[number]`, and `[struct]` array_kind = kind.kind if mojom.IsStringKind(array_kind): return "VectorFromNSArray(%s)" % accessor if self._IsObjCNumberKind(array_kind): return """^{ std::vector<%s> array; for (NSNumber *number in %s) { array.push_back(number.%s); } return array; }()""" % (_kind_to_objc_type[array_kind], accessor, _kind_to_nsnumber_getter[array_kind]) elif mojom.IsStringKind(array_kind): return """^{ std::vector<std::string> array; for (NSString *string in %s) { array.push_back(string.UTF8String); } return array; }()""" % accessor elif self._IsMojomStruct(array_kind): return """^{ std::vector<%s::%sPtr> array; for (%s%s *obj in %s) { array.push_back(obj.cppObjPtr); } return array; }()""" % (self._CppNamespace(), array_kind.name, self.class_prefix, array_kind.name, accessor) else: raise Exception("Unsupported array kind %s" % array_kind.spec) if mojom.IsMapKind(kind): # Only currently supporting: `{string: string}`, `{string: number}`, and # `{string: struct}` key_kind = kind.key_kind val_kind = kind.value_kind if mojom.IsStringKind(key_kind): if self._IsObjCNumberKind(val_kind): return """^{ base::flat_map<std::string, %s> map; for (NSString *key in %s) { map[key.UTF8String] = %s[key].%s; } return map; }()""" % (_kind_to_objc_type[val_kind], accessor, accessor, _kind_to_nsnumber_getter[val_kind]) elif mojom.IsStringKind(val_kind): return """^{ base::flat_map<std::string, std::string> map; for (NSString *key in %s) { map[key.UTF8String] = %s[key].UTF8String; } return map; }()""" % (accessor, accessor) elif self._IsMojomStruct(val_kind): return """^{ base::flat_map<std::string, %s::%sPtr> map; for (NSString *key in %s) { map[key.UTF8String] = %s[key].cppObjPtr; } return map; }()""" % (self._CppNamespace(), val_kind.name, accessor, accessor) else: raise Exception("Unsupported dictionary value kind %s" % val_kind.spec) else: raise Exception("Unsupported dictionary key kind %s" % key_kind.spec) return "%s" % accessor
def EncodeSuffix(kind): if mojom.IsEnumKind(kind): return EncodeSuffix(mojom.INT32) if mojom.IsInterfaceKind(kind) or mojom.IsInterfaceRequestKind(kind): return EncodeSuffix(mojom.MSGPIPE) return _kind_infos[kind].encode_suffix
def BitWidth(element): if element.kind in _bit_widths: return _bit_widths[element.kind] if mojom.IsEnumKind(element.kind): return '32' return ''
def IsEnum(element): return mojom.IsEnumKind(element.kind)
def _FormatEnumConstantDeclaration(self, constant): if mojom.IsEnumKind(constant.kind): return "constexpr %s %s = %s" % (self._GetNameForKind( constant.kind), constant.name, self._ConstantValue(constant))