class PnaclGen(WrapperGen): """PnaclGen generates shim code to bridge the Gcc ABI with PNaCl. This subclass of WrapperGenerator takes the IDL sources and generates shim methods for bridging the calling conventions between GCC and PNaCl (LLVM). Some of the PPAPI methods do not need shimming, so this will also detect those situations and provide direct access to the original PPAPI methods (rather than the shim methods). """ def __init__(self): WrapperGen.__init__(self, 'Pnacl', 'Pnacl Shim Gen', 'pnacl', 'Generate the PNaCl shim.') self.cgen = CGen() self._skip_opt = False ############################################################ def OwnHeaderFile(self): """Return the header file that specifies the API of this wrapper. We do not generate the header files. """ return 'ppapi/generators/pnacl_shim.h' def InterfaceVersionNeedsWrapping(self, iface, version): """Return true if the interface+version has ANY methods that need wrapping. """ if self._skip_opt: return True for member in iface.GetListOf('Member'): release = member.GetRelease(version) if self.MemberNeedsWrapping(member, release): return True return False def MemberNeedsWrapping(self, member, release): """Return true if a particular member function at a particular release needs wrapping. """ if self._skip_opt: return True if not member.InReleases([release]): return False ret, name, array, args_spec = self.cgen.GetComponents( member, release, 'store') return self.TypeNeedsWrapping(ret, []) or self.ArgsNeedWrapping(args_spec) def ArgsNeedWrapping(self, args): """Return true if any parameter in the list needs wrapping. """ for arg in args: (type_str, name, array_dims, more_args) = arg if self.TypeNeedsWrapping(type_str, array_dims): return True return False def TypeNeedsWrapping(self, type_node, array_dims): """Return true if a parameter type needs wrapping. Currently, this is true for byval aggregates. """ is_aggregate = type_node.startswith('struct') or \ type_node.startswith('union') is_reference = (type_node.find('*') != -1 or array_dims != []) return is_aggregate and not is_reference ############################################################ def ConvertByValueReturnType(self, ret, args_spec): if self.TypeNeedsWrapping(ret, array_dims=[]): args_spec = [(ret, '_struct_result', [], None)] + args_spec ret2 = 'void' wrap_return = True else: ret2 = ret wrap_return = False return wrap_return, ret2, args_spec def ConvertByValueArguments(self, args_spec): args = [] for type_str, name, array_dims, more_args in args_spec: if self.TypeNeedsWrapping(type_str, array_dims): type_str += '*' args.append((type_str, name, array_dims, more_args)) return args def FormatArgs(self, c_operator, args_spec): args = [] for type_str, name, array_dims, more_args in args_spec: if self.TypeNeedsWrapping(type_str, array_dims): args.append(c_operator + name) else: args.append(name) return ', '.join(args) def GenerateWrapperForPPBMethod(self, iface, member): result = [] func_prefix = self.WrapperMethodPrefix(iface.node, iface.release) ret, name, array, cspec = self.cgen.GetComponents( member, iface.release, 'store') wrap_return, ret2, cspec2 = self.ConvertByValueReturnType(ret, cspec) cspec2 = self.ConvertByValueArguments(cspec2) sig = self.cgen.Compose(ret2, name, array, cspec2, prefix=func_prefix, func_as_ptr=False, include_name=True, unsized_as_ptr=False) result.append('static %s {\n' % sig) result.append(' const struct %s *iface = %s.real_iface;\n' % (iface.struct_name, self.GetWrapperInfoName(iface))) return_prefix = '' if wrap_return: return_prefix = '*_struct_result = ' elif ret != 'void': return_prefix = 'return ' result.append( ' %siface->%s(%s);\n}\n\n' % (return_prefix, member.GetName(), self.FormatArgs('*', cspec))) return result def GenerateWrapperForPPPMethod(self, iface, member): result = [] func_prefix = self.WrapperMethodPrefix(iface.node, iface.release) sig = self.cgen.GetSignature(member, iface.release, 'store', func_prefix, False) result.append('static %s {\n' % sig) result.append(' const struct %s *iface = %s.real_iface;\n' % (iface.struct_name, self.GetWrapperInfoName(iface))) ret, name, array, cspec = self.cgen.GetComponents( member, iface.release, 'store') wrap_return, ret2, cspec = self.ConvertByValueReturnType(ret, cspec) cspec2 = self.ConvertByValueArguments(cspec) temp_fp = self.cgen.Compose(ret2, name, array, cspec2, prefix='temp_fp', func_as_ptr=True, include_name=False, unsized_as_ptr=False) cast = self.cgen.Compose(ret2, name, array, cspec2, prefix='', func_as_ptr=True, include_name=False, unsized_as_ptr=False) result.append(' %s =\n ((%s)iface->%s);\n' % (temp_fp, cast, member.GetName())) return_prefix = '' if wrap_return: result.append(' %s _struct_result;\n' % ret) elif ret != 'void': return_prefix = 'return ' result.append(' %stemp_fp(%s);\n' % (return_prefix, self.FormatArgs('&', cspec))) if wrap_return: result.append(' return _struct_result;\n') result.append('}\n\n') return result def GenerateRange(self, ast, releases, options): """Generate shim code for a range of releases. """ self._skip_opt = GetOption('disable_pnacl_opt') self.SetOutputFile(GetOption('pnaclshim')) return WrapperGen.GenerateRange(self, ast, releases, options)
class RPCGen(object): def __init__(self): self.cgen = CGen() self.interfaceStructs = [] self.pppInterfaceGetters = [] def AddProp(self, release, s, prefix, member, isOutParam=False, callnode=None, derefSizeIs=True): out = '' key = member.GetName() if not member.InReleases([release]): out += '/* skipping %s */\n' % key return type = member.GetType(release).GetName() array = member.GetOneOf('Array') interfaceMember = member.parent interface = interfaceMember.parent.parent customSerializer = getCustom(interface.GetName(), interfaceMember.GetName(), member.GetName()) array = customSerializer.get('array', array) isOutParam = customSerializer.get('isOutParam', isOutParam) if isOutParam: out += ' AddProp(' + s + ', "' + key + '", PointerToString(' + prefix + key + '));\n' elif array: if customSerializer: type = customSerializer.get('arrayType', type) count = array.GetProperty('FIXED') if isinstance(array, IDLNode) else None if not count: size_is = member.GetProperty('size_is()') if size_is: size_is = size_is[0] count = prefix + size_is if callnode: for param in callnode.GetListOf('Param'): if param.GetName() == size_is: if self.cgen.GetParamMode( param) == 'out' and derefSizeIs: count = '*' + count break else: size_as = member.GetProperty('size_as') count = size_as if customSerializer: count = customSerializer.get('arraySize', count) out += ' {\n' out += ' BeginProp(' + s + ', "' + key + '");\n' out += ' BeginElements(' + s + ');\n' out += ' for (uint32_t _n = 0; ' if count: out += '_n < ' + count else: sentinel = customSerializer.get('arraySentinel', '0') out += prefix + key + '[_n] != ' + sentinel out += '; ++_n) {\n' out += ' AddElement(' + s + ', ToString_' + type + '(' + prefix + key + '[_n]));\n' out += ' }\n' out += ' EndElements(' + s + ');\n' out += ' }\n' else: out += ' AddProp(' + s + ', "' + key + '", ToString_' + type + '(' + prefix + key + '));\n' return out def FromJSON(self, release, prefix, outvalue, node, create, callnode=None): out = '' type = node.GetType(release).GetName() array = node.GetOneOf('Array') interfaceMember = node.parent interface = interfaceMember.parent.parent customParser = getCustom(interface.GetName(), interfaceMember.GetName(), node.GetName()) array = customParser.get('array', array) create = customParser.get('create', create) name = node.GetName() outvalue = prefix + outvalue if array: if customParser: type = customParser.get('arrayType', type) fixed = array.GetProperty('FIXED') if isinstance(array, IDLNode) else None count = fixed if type == 'char': assert count > 0 out += ' FromJSON_charArray(iterator, ' + outvalue + ', ' + str( count) + ');\n' else: if not count: size_is = node.GetProperty('size_is()') if size_is: size_is = size_is[0] count = prefix + size_is if callnode: for param in callnode.GetListOf('Param'): if param.GetName() == size_is: if self.cgen.GetParamMode(param) == 'out': count = '*' + count break else: size_as = node.GetProperty('size_as') count = size_as if customParser: count = customParser.get('arraySize', count) out += '\n' out += ' {\n' out += ' size_t children = iterator.expectArrayAndGotoFirstItem();\n' if count: out += ' if (children > ' + count + ') {\n' out += ' Fail("Too many items in array\\n", "");\n' out += ' }\n' if create and not fixed: if not count: count = 'children' out += ' ' + outvalue + ' = new ' + self.cgen.GetTypeByMode( node, release, 'store') + '[' + count + '];\n' out += ' for (uint32_t _n = 0; _n < children; ++_n) {\n' out += ' FromJSON_' + type + '(iterator, (' + outvalue + ')[_n]);\n' out += ' }\n' out += ' // FIXME Null out remaining items?\n' out += ' }\n' else: out += ' FromJSON_' + type + '(iterator, ' + outvalue + ');\n' return out def MemberFromJSON(self, release, prefix, member, create): key = member.GetName() if not member.InReleases([release]): return '/* skipping %s */\n' % key return self.FromJSON(release, prefix, key, member, create) DerefOutType = { 'Array': { 'out': '*' }, 'Enum': '*', 'Struct': '*', 'cstr_t': '*', 'TypeValue': '*', } def DefineInterfaceMethodSerializer(self, iface, releases, node, release): customSerializer = getCustom(iface.GetName(), node.GetName(), None) if not node.InReleases([release]): return '/* skipping %s */\n' % node.GetName() if customSerializer and customSerializer.get('skip', False): return self.cgen.GetSignature(node, release, 'ref', '', func_as_ptr=False, include_version=True) + ";\n" out = '' out += 'static ' out += self.cgen.GetSignature(node, release, 'ref', '', func_as_ptr=False, include_version=True) out += ' {\n' out += ' stringstream ss;\n' out += ' BeginProps(ss);\n' out += ' AddProp(ss, "__interface", "\\"' + iface.GetName( ) + '\\"");\n' out += ' AddProp(ss, "__version", "\\"' + iface.GetVersion( release) + '\\"");\n' out += ' AddProp(ss, "__method", "\\"' + node.GetName() + '\\"");\n' callnode = node.GetOneOf('Callspec') hasOutParams = False if callnode: for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode(param, release, mode) mode = getCustom(param.parent.parent.parent.GetName(), param.parent.GetName(), param.GetName()).get('mode', mode) if mode == "out" or mode == "inout": hasOutParams = hasOutParams or not (ntype == 'mem_t' and mode == "inout") out += self.AddProp(release, 'ss', '', param, mode == "out", callnode) out += ' EndProps(ss);\n' if node.GetProperty('ref'): mode = 'ref' else: mode = 'store' rtype = self.cgen.GetTypeByMode(node.GetType(release), release, 'store') out += '#ifndef INTERPOSE\n' out += ' ' if rtype != 'void' or hasOutParams: out += 'string json = RPCWithResult' else: out += 'RPC' if customSerializer and customSerializer.get('maybeNonMainThread', False): out += '<MaybeNonMainThread>' else: out += '<MainThreadOnly>' out += '(ss);\n' if rtype != 'void' or hasOutParams: if rtype != 'void': out += ' ' + rtype + ' rval;\n' out += ' JSONIterator iterator(json);\n' out += ' iterator.expectArrayAndGotoFirstItem();\n' if hasOutParams: out += ' iterator.expectArrayAndGotoFirstItem();\n' if rtype != 'void': customRval = getCustom(iface.GetName(), node.GetName(), "rval").get('convert') if customRval: out += customRval else: out += ' FromJSON_' + node.GetType( release).GetName() + '(iterator, rval);\n' if hasOutParams: out += ' iterator.expectObjectAndGotoFirstProperty();\n' for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode( param, release, mode) mode = getCustom(param.parent.parent.parent.GetName(), param.parent.GetName(), param.GetName()).get('mode', mode) if mode == "out" or mode == "inout": if ntype == 'mem_t' and mode == "inout": continue if ntype == 'Struct' and mode == 'out': out += ' if (!!' + param.GetName() + ') {\n' to_indent = ' iterator.skip();\n' deref = self.DerefOutType.get(ntype, '') if isinstance(deref, dict): deref = deref.get(mode, '') to_indent += self.FromJSON(release, '', deref + param.GetName(), param, mode == 'out', callnode) if ntype == 'Struct' and mode == 'out': out += re.sub(r"(^|\n)(?!(\n|$))", r'\1' + (2 * ' '), to_indent) out += ' }\n' else: out += to_indent if rtype != 'void': out += ' return rval;\n' out += '#else // !INTERPOSE\n' out += ' printf("%s\\n", ss.str().c_str());\n' #out += ' printf("Calling: %p\\n", RealGetInterface("' + self.cgen.GetInterfaceString(iface, iface.GetVersion(release)) + '"));\n' #out += ' printf(" -> %p\\n", ((' + self.cgen.GetStructName(iface, release, include_version=True) + '*)RealGetInterface("' + self.cgen.GetInterfaceString(iface, iface.GetVersion(release)) + '"))->' + node.GetName() + ');\n' out += ' ' rtype = self.cgen.GetTypeByMode(node.GetType(release), release, 'return') params = [] for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode(param, release, mode) if mode == "in" and param.GetType( release).GetName() == 'PP_CompletionCallback': out += 'PP_CompletionCallback logging_' + param.GetName( ) + ';\n' out += ' logging_' + param.GetName( ) + '.func = &Logging_PP_CompletionCallback;\n' out += ' logging_' + param.GetName( ) + '.user_data = new PP_CompletionCallback(' + param.GetName( ) + ');\n' out += ' logging_' + param.GetName( ) + '.flags = ' + param.GetName() + '.flags;\n' out += ' ' params.append('logging_' + param.GetName()) elif mode == "in" and param.GetType( release).GetName() == 'PPP_Class_Deprecated': out += 'Logging_PPP_Class_Deprecated_holder* logging_' + param.GetName( ) + ' = new Logging_PPP_Class_Deprecated_holder();\n' out += ' logging_' + param.GetName( ) + '->_real_PPP_Class_Deprecated = ' + param.GetName() + ';\n' out += ' logging_' + param.GetName( ) + '->object = object_data;\n' out += ' object_data = logging_' + param.GetName() + ';\n' out += ' ' params.append('&_interpose_PPP_Class_Deprecated_1_0') elif mode == "return" and param.GetType(release).GetName( ) == 'PPB_Audio_Callback' and param.GetVersion(release) == "1.0": out += 'Logging_PPB_Audio_Callback_1_0_holder* ' + param.GetName( ) + '_holder = new Logging_PPB_Audio_Callback_1_0_holder();\n' out += ' ' + param.GetName( ) + '_holder->func = ' + param.GetName() + ';\n' out += ' ' + param.GetName( ) + '_holder->user_data = user_data;\n' out += ' user_data = ' + param.GetName() + '_holder;\n' out += ' ' params.append('Logging_PPB_Audio_Callback_1_0') else: params.append(param.GetName()) if rtype != 'void': out += rtype + ' rval = ' out += '((' + self.cgen.GetStructName( iface, release, include_version=True ) + '*)RealGetInterface("' + self.cgen.GetInterfaceString( iface, iface.GetVersion(release)) + '"))->' + node.GetName( ) + '(' + ', '.join(params) + ');\n' if rtype != 'void' or hasOutParams: out += ' printf("RPC response: [");\n' if hasOutParams: out += ' printf("[");\n' if rtype != 'void': out += ' printf("%s", ToString_' + node.GetType( release).GetName() + '(rval).c_str());\n' if hasOutParams: if rtype != 'void': out += ' printf(",");\n' out += ' std::stringstream os;\n' out += ' BeginProps(os);\n' for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode( param, release, mode) if mode == "out" or mode == "inout": if mode == "out" and (ntype == 'Struct' or ntype == 'TypeValue'): out += ' if (!!' + param.GetName() + ') {\n' out += self.AddProp(release, 'os', '', param, False, callnode) if mode == "out" and (ntype == 'Struct' or ntype == 'TypeValue'): out += ' }\n' out += ' EndProps(os);\n' out += ' printf("%s]", os.str().c_str());\n' out += ' printf("]\\n");\n' if rtype != 'void': out += ' return rval;\n' out += '#endif // !INTERPOSE\n' out += '}\n' return out def DefineInterfaceMethodParser(self, iface, releases, node, release): if not node.InReleases([release]): return '/* skipping %s */\n' % node.GetName() version = self.GetNodeName(iface, release, releases) out = '' out += 'char* Call_%s_%s(const %s* _interface, JSONIterator& iterator) {\n' % ( iface.GetName(), node.GetName(), version) callnode = node.GetOneOf('Callspec') params = [] hasOutParams = False for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ptype, pname, parray, pspec = self.cgen.GetComponents( param, release, "store") out += ' ' + self.cgen.Compose(ptype, pname, parray, pspec, '', func_as_ptr=True, include_name=True, unsized_as_ptr=True) + ';\n' if mode == 'out': if len(parray) > 0: out += ' iterator.skip();\n' out += ' PointerValueFromJSON(iterator, ' + pname + ');\n' else: out += ' iterator.skip();\n' out += self.FromJSON(release, '', pname, param, True, callnode) hasOutParams = hasOutParams or mode == "out" or mode == "inout" if node.GetProperty('ref'): mode = 'ref' else: mode = 'store' rtype = self.cgen.GetTypeByMode(node.GetType(release), release, 'store') out += ' ' if rtype != 'void': out += rtype + ' rval;\n' out += ' rval = ' params = [] for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode(param, release, mode) ptype, pname, parray, pspec = self.cgen.GetComponents( param, release, mode) if mode == 'out' or ntype == 'Struct' or (mode == 'constptr_in' and ntype == 'TypeValue'): pname = '&' + pname pname = '(' + self.cgen.Compose(ptype, pname, parray, pspec, '', func_as_ptr=True, include_name=False, unsized_as_ptr=True) + ')' + pname params.append(pname) out += '_interface->' + node.GetName() + '(' + ", ".join( params) + ');\n' if rtype != 'void' or hasOutParams: typeref = node.GetType(release) if hasOutParams: out += ' stringstream os;\n' out += ' BeginElements(os);\n' if rtype != 'void': out += ' AddElement(os, ToString_' + typeref.GetName( ) + '(rval).c_str());\n' out += ' BeginElement(os);\n' out += ' BeginProps(os);\n' for param in callnode.GetListOf('Param'): mode = self.cgen.GetParamMode(param) ntype, mode = self.cgen.GetRootTypeMode( param, release, mode) ptype, pname, parray, pspec = self.cgen.GetComponents( param, release, mode) if mode == 'out' or mode == 'inout': out += self.AddProp(release, 'os', '', param, False, callnode, derefSizeIs=False) out += ' EndProps(os);\n' out += ' EndElements(os);\n' out += ' return strdup(os.str().c_str());\n' else: out += ' return strdup(ToString_' + typeref.GetName( ) + '(rval).c_str());\n' else: out += ' return nullptr;\n' out += '}\n' return out def DefineInterface(self, node, releases, declareOnly): out = '' if node.GetName() == "PPB_NaCl_Private": # skip return out isPPP = node.GetName()[0:4] == "PPP_" build_list = node.GetUniqueReleases(releases) for release in build_list: name = self.cgen.GetStructName(node, release, include_version=True) if declareOnly: out += '#ifdef INTERPOSE\n' out += 'static ' + name + ' *_real_' + name + ';\n' out += '#endif // INTERPOSE\n' if isPPP: version = self.GetNodeName(node, release, build_list) if declareOnly: out += 'static char* Call_%s(void* _interface, JSONIterator& iterator);\n' % ( version) continue members = node.GetListOf('Member') for member in members: out += self.DefineInterfaceMethodParser( node, build_list, member, release) out += 'char* Call_%s(const void* _interface, JSONIterator& iterator) {\n' % ( version) out += ' iterator.skip();\n' out += ' const Token& member = iterator.getCurrentStringAndGotoNext();\n' out += ' string memberName = member.value();\n' for member in members: if not member.InReleases([release]): out += '/* skipping %s */\n' % member.GetName() continue out += ' if (!memberName.compare("' + member.GetName( ) + '")) {\n' out += ' return Call_' + node.GetName( ) + '_' + member.GetName( ) + '((const ' + version + '*)_interface, iterator);\n' out += ' }\n' out += ' return nullptr;\n' out += '}\n' self.pppInterfaceGetters.append( (self.cgen.GetInterfaceString(node, node.GetVersion(release)), 'Call_' + version)) continue version = self.cgen.GetStructName(node, release, include_version=True) if declareOnly: out += 'const string ToString_%s(const %s *v);\n' % ( node.GetName(), version) continue ns = 'ns_' + version out += 'namespace ' + ns + ' {\n' members = node.GetListOf('Member') for member in members: out += self.DefineInterfaceMethodSerializer( node, releases, member, release) out += '}\n' self.interfaceStructs.append( (self.cgen.GetInterfaceString(node, node.GetVersion(release)), '_' + name)) out += 'static ' + name + ' _' + name + ' = {\n' for member in members: if not member.InReleases([release]): continue memberName = self.cgen.GetStructName(member, release, True) out += ' ' + ns + '::' + memberName + ',\n' out += '};\n' out += 'const string ToString_%s(const %s *v) {\n' % ( node.GetName(), version) out += ' stringstream s;\n' out += ' s << v;\n' out += ' return s.str();\n' out += '}\n' return out def GetNodeName(self, node, release, build_list): return self.cgen.GetStructName( node, release, include_version=(release != build_list[-1])) @staticmethod def SerializerAndParserSignatures(typename, type): s = ('const string ToString_%s(const %s *v)', 'const string ToString_%s(const %s &v)', 'void FromJSON_%s(JSONIterator& iterator, %s &value)') return (sig % (typename, type) for sig in s) def DefineTypedefSerializerAndParser(self, node, releases, declareOnly): out = '' build_list = node.GetUniqueReleases(releases) for release in build_list: type = self.GetNodeName(node, release, build_list) typeref = node.GetType(release) (toStringFromPointer, toStringFromRef, fromJSONToRef) = self.SerializerAndParserSignatures( node.GetName(), type) isFuncPtr = node.GetOneOf('Callspec') if declareOnly: if not isFuncPtr: out += toStringFromPointer + ";\n" out += toStringFromRef + ";\n" out += fromJSONToRef + ";\n" continue if not isFuncPtr: out += toStringFromPointer + ' {\n' out += ' return ToString_%s(v);\n' % (typeref.GetName()) out += '}\n' out += toStringFromRef + ' {\n' if isFuncPtr: out += ' return PointerToString(v);\n' else: out += ' return ToString_%s(&v);\n' % (node.GetName()) out += '}\n' out += fromJSONToRef + ' {\n' if isFuncPtr: out += ' PointerValueFromJSON(iterator, value);\n' else: out += ' FromJSON_%s(iterator, value);\n' % ( typeref.GetName()) out += '}\n' return out def DefineStructSerializerAndParser(self, node, releases, declareOnly): out = '' build_list = node.GetUniqueReleases(releases) for release in build_list: name = node.GetName() version = self.GetNodeName(node, release, build_list) (toStringFromPointer, toStringFromRef, fromJSONToRef) = self.SerializerAndParserSignatures( name, version) if declareOnly: out += toStringFromPointer + ";\n" out += toStringFromRef + ";\n" out += fromJSONToRef + ";\n" continue out += toStringFromPointer + ' {\n' out += ' if (!v) {\n' out += ' return "null";\n' out += ' }\n' out += ' return ToString_%s(*v);\n' % (name) out += '}\n' out += toStringFromRef + ' {\n' out += ' stringstream x;\n' out += ' BeginProps(x);\n' members = node.GetListOf('Member') for member in members: out += self.AddProp(release, 'x', 'v.', member) out += ' EndProps(x);\n' out += ' return x.str();\n' out += '}\n' out += fromJSONToRef + ' {\n' out += ' const JSON::Token& current = iterator.getCurrentAndGotoNext();\n' # FIXME Should we warn here somehow? It might be ok to return null in # error conditions, so maybe not. out += ' if (current.isPrimitive() && !current.value().compare("null")) {\n' out += ' return;\n' out += ' }\n' out += ' if (!current.isObject()) {\n' out += ' Fail("Expected object!", "");\n' out += ' }\n' if node.GetProperty('union'): out += ' string name = iterator.getCurrentStringAndGotoNext().value();\n' out += " else ".join( map( lambda m: ' if (!name.compare(\"' + m.GetName( ) + '\")) {\n ' + self.MemberFromJSON( release, 'value.', m, False) + ' }', members)) + "\n" else: for member in members: typeref = member.GetType(release) out += ' iterator.skip();\n' out += self.MemberFromJSON(release, 'value.', member, False) out += '}\n' return out def DefineEnumSerializerAndParser(self, node, releases, declareOnly): if node.GetProperty('unnamed'): return '' out = '' name = node.GetName() (toStringFromPointer, toStringFromRef, fromJSONToRef) = self.SerializerAndParserSignatures(name, name) if declareOnly: out += toStringFromPointer + ";\n" out += toStringFromRef + ";\n" out += fromJSONToRef + ";\n" return out out += toStringFromPointer + ' {\n' out += ' switch (*v) {\n' next = 0 emitted = set() for child in node.GetListOf('EnumItem'): value = child.GetName() label = child.GetProperty('VALUE') if not label: label = str(next) next = next + 1 if label in emitted: continue emitted.add(label) emitted.add(value) out += ' case ' + label + ':\n' out += ' return "\\"' + value + '\\"";\n' out += ' default:\n' out += ' return "\\"???\\"";\n' out += ' }\n' out += '}\n' out += toStringFromRef + ' {\n' out += ' return ToString_%s(&v);\n' % (name) out += '}\n' out += fromJSONToRef + ' {\n' out += ' long int v;\n' out += ' FromJSON_int(iterator, v);\n' out += ' value = %s(v);\n' % (name) out += '}\n' return out def Define(self, node, releases, declareOnly): # Skip if this node is not in this release if not node.InReleases(releases): return "/* skipping %s */\n" % node if node.IsA('Typedef'): return self.DefineTypedefSerializerAndParser( node, releases, declareOnly) if node.IsA('Struct'): return self.DefineStructSerializerAndParser( node, releases, declareOnly) if node.IsA('Enum'): return self.DefineEnumSerializerAndParser(node, releases, declareOnly) if node.IsA('Interface'): return self.DefineInterface(node, releases, declareOnly) return ''