• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
2# reserved. Use of this source code is governed by a BSD-style license that
3# can be found in the LICENSE file.
4
5from __future__ import absolute_import
6from cef_parser import *
7
8
9def make_cpptoc_impl_proto(name, func, parts):
10  if isinstance(func, obj_function_virtual):
11    proto = parts['retval'] + ' CEF_CALLBACK'
12  else:
13    proto = 'CEF_EXPORT ' + parts['retval']
14
15  proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
16  return proto
17
18
19def make_cpptoc_function_impl_existing(cls, name, func, impl, defined_names):
20  notify(name + ' has manual edits')
21
22  # retrieve the C API prototype parts
23  parts = func.get_capi_parts(defined_names)
24
25  changes = format_translation_changes(impl, parts)
26  if len(changes) > 0:
27    notify(name + ' prototype changed')
28
29  return make_cpptoc_impl_proto(
30      name, func, parts) + '{' + changes + impl['body'] + '\n}\n\n'
31
32
33def make_cpptoc_function_impl_new(cls, name, func, defined_names, base_scoped):
34  # Special handling for the cef_shutdown global function.
35  is_cef_shutdown = name == 'cef_shutdown' and isinstance(
36      func.parent, obj_header)
37
38  # retrieve the C API prototype parts
39  parts = func.get_capi_parts(defined_names)
40  result = make_cpptoc_impl_proto(name, func, parts) + ' {'
41
42  if isinstance(func.parent, obj_class) and \
43      not func.parent.has_attrib('no_debugct_check') and \
44      not base_scoped:
45    result += '\n  shutdown_checker::AssertNotShutdown();\n'
46
47  invalid = []
48
49  # retrieve the function arguments
50  args = func.get_arguments()
51
52  # determine the argument types
53  for arg in args:
54    if arg.get_arg_type() == 'invalid':
55      invalid.append(arg.get_name())
56
57  # retrieve the function return value
58  retval = func.get_retval()
59  retval_type = retval.get_retval_type()
60  if retval_type == 'invalid':
61    invalid.append('(return value)')
62    retval_default = ''
63  else:
64    retval_default = retval.get_retval_default(True)
65    if len(retval_default) > 0:
66      retval_default = ' ' + retval_default
67
68  if len(invalid) > 0:
69    notify(name + ' could not be autogenerated')
70    # code could not be auto-generated
71    result += '\n  // BEGIN DELETE BEFORE MODIFYING'
72    result += '\n  // AUTO-GENERATED CONTENT'
73    result += '\n  // COULD NOT IMPLEMENT DUE TO: ' + ', '.join(invalid)
74    result += '\n  #pragma message("Warning: "__FILE__": ' + name + ' is not implemented")'
75    result += '\n  // END DELETE BEFORE MODIFYING'
76    result += '\n}\n\n'
77    return result
78
79  result += '\n  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING\n'
80
81  result_len = len(result)
82
83  optional = []
84
85  # parameter verification
86  if isinstance(func, obj_function_virtual):
87    result += '\n  DCHECK(self);'\
88              '\n  if (!self)'\
89              '\n    return'+retval_default+';'
90
91  for arg in args:
92    arg_type = arg.get_arg_type()
93    arg_name = arg.get_type().get_name()
94
95    # skip optional params
96    optional_params = arg.parent.get_attrib_list('optional_param')
97    if not optional_params is None and arg_name in optional_params:
98      optional.append(arg_name)
99      continue
100
101    comment = '\n  // Verify param: ' + arg_name + '; type: ' + arg_type
102
103    if arg_type == 'simple_byref' or arg_type == 'simple_byref_const' or \
104       arg_type == 'simple_byaddr' or arg_type == 'bool_byref' or arg_type == 'bool_byaddr' or \
105       arg_type == 'struct_byref_const' or arg_type == 'struct_byref' or \
106       arg_type == 'string_byref_const' or arg_type == 'string_byref' or \
107       arg_type == 'refptr_same' or arg_type == 'refptr_same_byref' or \
108       arg_type == 'refptr_diff' or arg_type == 'refptr_diff_byref' or \
109       arg_type == 'ownptr_same' or arg_type == 'ownptr_same_byref' or \
110       arg_type == 'ownptr_diff' or arg_type == 'ownptr_diff_byref' or \
111       arg_type == 'rawptr_same' or arg_type == 'rawptr_same_byref' or \
112       arg_type == 'rawptr_diff' or arg_type == 'rawptr_diff_byref' or \
113       arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const' or \
114       arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const' or \
115       arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
116      result += comment+\
117                '\n  DCHECK('+arg_name+');'\
118                '\n  if (!'+arg_name+')'\
119                '\n    return'+retval_default+';'
120    elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
121        arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref' or \
122        arg_type == 'ownptr_vec_same_byref' or arg_type == 'ownptr_vec_diff_byref' or \
123        arg_type == 'rawptr_vec_same_byref' or arg_type == 'rawptr_vec_diff_byref':
124      result += comment+\
125                '\n  DCHECK('+arg_name+'Count && (*'+arg_name+'Count == 0 || '+arg_name+'));'\
126                '\n  if (!'+arg_name+'Count || (*'+arg_name+'Count > 0 && !'+arg_name+'))'\
127                '\n    return'+retval_default+';'
128    elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \
129        arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \
130        arg_type == 'ownptr_vec_same_byref_const' or arg_type == 'ownptr_vec_diff_byref_const' or \
131        arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const':
132      result += comment+\
133                '\n  DCHECK('+arg_name+'Count == 0 || '+arg_name+');'\
134                '\n  if ('+arg_name+'Count > 0 && !'+arg_name+')'\
135                '\n    return'+retval_default+';'
136
137    # check index params
138    index_params = arg.parent.get_attrib_list('index_param')
139    if not index_params is None and arg_name in index_params:
140      result += comment+\
141                '\n  DCHECK_GE('+arg_name+', 0);'\
142                '\n  if ('+arg_name+' < 0)'\
143                '\n    return'+retval_default+';'
144
145  if len(optional) > 0:
146    # Wrap the comment at 80 characters.
147    str = '\n  // Unverified params: ' + optional[0]
148    for name in optional[1:]:
149      str += ','
150      if len(str) + len(name) + 1 > 80:
151        result += str
152        str = '\n  //'
153      str += ' ' + name
154    result += str
155
156  if len(result) != result_len:
157    result += '\n'
158  result_len = len(result)
159
160  # parameter translation
161  params = []
162
163  for arg in args:
164    arg_type = arg.get_arg_type()
165    arg_name = arg.get_type().get_name()
166
167    comment = '\n  // Translate param: ' + arg_name + '; type: ' + arg_type
168
169    if arg_type == 'simple_byval' or arg_type == 'simple_byaddr':
170      params.append(arg_name)
171    elif arg_type == 'simple_byref' or arg_type == 'simple_byref_const':
172      data_type = arg.get_type().get_type()
173      default = arg.get_type().get_result_simple_default()
174      result += comment+\
175                '\n  '+data_type+' '+arg_name+'Val = '+arg_name+'?*'+arg_name+':'+default+';'
176      params.append(arg_name + 'Val')
177    elif arg_type == 'bool_byval':
178      params.append(arg_name + '?true:false')
179    elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr':
180      result += comment+\
181                '\n  bool '+arg_name+'Bool = ('+arg_name+' && *'+arg_name+')?true:false;'
182      if arg_type == 'bool_byref':
183        params.append(arg_name + 'Bool')
184      else:
185        params.append('&' + arg_name + 'Bool')
186    elif arg_type == 'struct_byref_const':
187      struct_type = arg.get_type().get_type()
188      result += comment+\
189                '\n  '+struct_type+' '+arg_name+'Obj;'\
190                '\n  if ('+arg_name+')'\
191                '\n    '+arg_name+'Obj.Set(*'+arg_name+', false);'
192      params.append(arg_name + 'Obj')
193    elif arg_type == 'struct_byref':
194      struct_type = arg.get_type().get_type()
195      result += comment+\
196                '\n  '+struct_type+' '+arg_name+'Obj;'\
197                '\n  if ('+arg_name+')'\
198                '\n    '+arg_name+'Obj.AttachTo(*'+arg_name+');'
199      params.append(arg_name + 'Obj')
200    elif arg_type == 'string_byref_const':
201      params.append('CefString(' + arg_name + ')')
202    elif arg_type == 'string_byref':
203      result += comment+\
204                '\n  CefString '+arg_name+'Str('+arg_name+');'
205      params.append(arg_name + 'Str')
206    elif arg_type == 'refptr_same' or arg_type == 'refptr_diff':
207      ptr_class = arg.get_type().get_ptr_type()
208      if arg_type == 'refptr_same':
209        params.append(ptr_class + 'CppToC::Unwrap(' + arg_name + ')')
210      else:
211        params.append(ptr_class + 'CToCpp::Wrap(' + arg_name + ')')
212    elif arg_type == 'ownptr_same' or arg_type == 'rawptr_same':
213      ptr_class = arg.get_type().get_ptr_type()
214      if arg_type == 'ownptr_same':
215        params.append(ptr_class + 'CppToC::UnwrapOwn(' + arg_name + ')')
216      else:
217        params.append(ptr_class + 'CppToC::UnwrapRaw(' + arg_name + ')')
218    elif arg_type == 'ownptr_diff' or arg_type == 'rawptr_diff':
219      ptr_class = arg.get_type().get_ptr_type()
220      result += comment+\
221                '\n  CefOwnPtr<'+ptr_class+'> '+arg_name+'Ptr('+ptr_class+'CToCpp::Wrap('+arg_name+'));'
222      if arg_type == 'ownptr_diff':
223        params.append('std::move(' + arg_name + 'Ptr)')
224      else:
225        params.append(arg_name + 'Ptr.get()')
226    elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
227      ptr_class = arg.get_type().get_ptr_type()
228      if arg_type == 'refptr_same_byref':
229        assign = ptr_class + 'CppToC::Unwrap(*' + arg_name + ')'
230      else:
231        assign = ptr_class + 'CToCpp::Wrap(*' + arg_name + ')'
232      result += comment+\
233                '\n  CefRefPtr<'+ptr_class+'> '+arg_name+'Ptr;'\
234                '\n  if ('+arg_name+' && *'+arg_name+')'\
235                '\n    '+arg_name+'Ptr = '+assign+';'\
236                '\n  '+ptr_class+'* '+arg_name+'Orig = '+arg_name+'Ptr.get();'
237      params.append(arg_name + 'Ptr')
238    elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const':
239      result += comment+\
240                '\n  std::vector<CefString> '+arg_name+'List;'\
241                '\n  transfer_string_list_contents('+arg_name+', '+arg_name+'List);'
242      params.append(arg_name + 'List')
243    elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const':
244      result += comment+\
245                '\n  std::map<CefString, CefString> '+arg_name+'Map;'\
246                '\n  transfer_string_map_contents('+arg_name+', '+arg_name+'Map);'
247      params.append(arg_name + 'Map')
248    elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
249      result += comment+\
250                '\n  std::multimap<CefString, CefString> '+arg_name+'Multimap;'\
251                '\n  transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);'
252      params.append(arg_name + 'Multimap')
253    elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
254        arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
255      vec_type = arg.get_type().get_vector_type()
256      if arg_type == 'simple_vec_byref':
257        assign = arg_name + '[i]'
258      elif arg_type == 'bool_vec_byref':
259        assign = arg_name + '[i]?true:false'
260      elif arg_type == 'refptr_vec_same_byref':
261        ptr_class = arg.get_type().get_ptr_type()
262        assign = ptr_class + 'CppToC::Unwrap(' + arg_name + '[i])'
263      elif arg_type == 'refptr_vec_diff_byref':
264        ptr_class = arg.get_type().get_ptr_type()
265        assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i])'
266      result += comment+\
267                '\n  std::vector<'+vec_type+' > '+arg_name+'List;'\
268                '\n  if ('+arg_name+'Count && *'+arg_name+'Count > 0 && '+arg_name+') {'\
269                '\n    for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\
270                '\n      '+arg_name+'List.push_back('+assign+');'\
271                '\n    }'\
272                '\n  }'
273      params.append(arg_name + 'List')
274    elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \
275        arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \
276        arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const':
277      vec_type = arg.get_type().get_vector_type()
278      if arg_type == 'simple_vec_byref_const':
279        assign = arg_name + '[i]'
280      elif arg_type == 'bool_vec_byref_const':
281        assign = arg_name + '[i]?true:false'
282      else:
283        ptr_class = arg.get_type().get_ptr_type()
284        if arg_type == 'refptr_vec_same_byref_const':
285          assign = ptr_class + 'CppToC::Unwrap(' + arg_name + '[i])'
286        elif arg_type == 'refptr_vec_diff_byref_const':
287          assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i])'
288        elif arg_type == 'rawptr_vec_same_byref_const':
289          assign = ptr_class + 'CppToC::UnwrapRaw(' + arg_name + '[i])'
290        elif arg_type == 'rawptr_vec_diff_byref_const':
291          assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i]).release()'
292      result += comment+\
293                '\n  std::vector<'+vec_type+' > '+arg_name+'List;'\
294                '\n  if ('+arg_name+'Count > 0) {'\
295                '\n    for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\
296                '\n      '+vec_type+' '+arg_name+'Val = '+assign+';'\
297                '\n      '+arg_name+'List.push_back('+arg_name+'Val);'\
298                '\n    }'\
299                '\n  }'
300      params.append(arg_name + 'List')
301    else:
302      raise Exception('Unsupported argument type %s for parameter %s in %s' %
303                      (arg_type, arg_name, name))
304
305  if len(result) != result_len:
306    result += '\n'
307  result_len = len(result)
308
309  if is_cef_shutdown:
310    result += '\n\n#if DCHECK_IS_ON()'\
311              '\n  shutdown_checker::SetIsShutdown();'\
312              '\n#endif\n'
313
314  # execution
315  result += '\n  // Execute\n  '
316
317  if retval_type != 'none':
318    # has a return value
319    if retval_type == 'simple':
320      result += retval.get_type().get_result_simple_type()
321    else:
322      result += retval.get_type().get_type()
323    result += ' _retval = '
324
325  if isinstance(func.parent, obj_class):
326    # virtual and static class methods
327    if isinstance(func, obj_function_virtual):
328      if cls.get_name() == func.parent.get_name():
329        # virtual method for the current class
330        result += func.parent.get_name() + 'CppToC::Get(self)->'
331      else:
332        # virtual method for a parent class
333        result += cls.get_name(
334        ) + 'CppToC::Get(reinterpret_cast<' + cls.get_capi_name() + '*>(self))->'
335    else:
336      result += func.parent.get_name() + '::'
337  result += func.get_name() + '('
338
339  if len(params) > 0:
340    result += '\n      ' + ',\n      '.join(params)
341
342  result += ');\n'
343
344  result_len = len(result)
345
346  # parameter restoration
347  for arg in args:
348    arg_type = arg.get_arg_type()
349    arg_name = arg.get_type().get_name()
350
351    comment = '\n  // Restore param: ' + arg_name + '; type: ' + arg_type
352
353    if arg_type == 'simple_byref':
354      result += comment+\
355                '\n  if ('+arg_name+')'\
356                '\n    *'+arg_name+' = '+arg_name+'Val;'
357    elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr':
358      result += comment+\
359                '\n  if ('+arg_name+')'\
360                '\n    *'+arg_name+' = '+arg_name+'Bool?true:false;'
361    elif arg_type == 'struct_byref':
362      result += comment+\
363                '\n  if ('+arg_name+')'\
364                '\n    '+arg_name+'Obj.DetachTo(*'+arg_name+');'
365    elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
366      ptr_class = arg.get_type().get_ptr_type()
367      if arg_type == 'refptr_same_byref':
368        assign = ptr_class + 'CppToC::Wrap(' + arg_name + 'Ptr)'
369      else:
370        assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + 'Ptr)'
371      result += comment+\
372                '\n  if ('+arg_name+') {'\
373                '\n    if ('+arg_name+'Ptr.get()) {'\
374                '\n      if ('+arg_name+'Ptr.get() != '+arg_name+'Orig) {'\
375                '\n        *'+arg_name+' = '+assign+';'\
376                '\n      }'\
377                '\n    } else {'\
378                '\n      *'+arg_name+' = nullptr;'\
379                '\n    }'\
380                '\n  }'
381    elif arg_type == 'string_vec_byref':
382      result += comment+\
383                '\n  cef_string_list_clear('+arg_name+');'\
384                '\n  transfer_string_list_contents('+arg_name+'List, '+arg_name+');'
385    elif arg_type == 'string_map_single_byref':
386      result += comment+\
387                '\n  cef_string_map_clear('+arg_name+');'\
388                '\n  transfer_string_map_contents('+arg_name+'Map, '+arg_name+');'
389    elif arg_type == 'string_map_multi_byref':
390      result += comment+\
391                '\n  cef_string_multimap_clear('+arg_name+');'\
392                '\n  transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');'
393    elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
394        arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
395      if arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref':
396        assign = arg_name + 'List[i]'
397      elif arg_type == 'refptr_vec_same_byref':
398        ptr_class = arg.get_type().get_ptr_type()
399        assign = ptr_class + 'CppToC::Wrap(' + arg_name + 'List[i])'
400      elif arg_type == 'refptr_vec_diff_byref':
401        ptr_class = arg.get_type().get_ptr_type()
402        assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + 'List[i])'
403      result += comment+\
404                '\n  if ('+arg_name+'Count && '+arg_name+') {'\
405                '\n    *'+arg_name+'Count = std::min('+arg_name+'List.size(), *'+arg_name+'Count);'\
406                '\n    if (*'+arg_name+'Count > 0) {'\
407                '\n      for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\
408                '\n        '+arg_name+'[i] = '+assign+';'\
409                '\n      }'\
410                '\n    }'\
411                '\n  }'
412    elif arg_type == 'rawptr_vec_diff_byref_const':
413      result += comment+\
414                '\n  if ('+arg_name+'Count > 0) {'\
415                '\n    for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\
416                '\n      delete '+arg_name+'List[i];'\
417                '\n    }'\
418                '\n  }'
419
420  if len(result) != result_len:
421    result += '\n'
422  result_len = len(result)
423
424  if len(result) != result_len:
425    result += '\n'
426  result_len = len(result)
427
428  # return translation
429  if retval_type != 'none':
430    # has a return value
431    result += '\n  // Return type: ' + retval_type
432    if retval_type == 'simple' or retval_type == 'bool':
433      result += '\n  return _retval;'
434    elif retval_type == 'string':
435      result += '\n  return _retval.DetachToUserFree();'
436    elif retval_type == 'refptr_same':
437      ptr_class = retval.get_type().get_ptr_type()
438      result += '\n  return ' + ptr_class + 'CppToC::Wrap(_retval);'
439    elif retval_type == 'refptr_diff':
440      ptr_class = retval.get_type().get_ptr_type()
441      result += '\n  return ' + ptr_class + 'CToCpp::Unwrap(_retval);'
442    elif retval_type == 'ownptr_same':
443      ptr_class = retval.get_type().get_ptr_type()
444      result += '\n  return ' + ptr_class + 'CppToC::WrapOwn(std::move(_retval));'
445    elif retval_type == 'ownptr_diff':
446      ptr_class = retval.get_type().get_ptr_type()
447      result += '\n  return ' + ptr_class + 'CToCpp::UnwrapOwn(std::move(_retval));'
448    else:
449      raise Exception('Unsupported return type %s in %s' % (retval_type, name))
450
451  if len(result) != result_len:
452    result += '\n'
453
454  result += '}\n\n'
455  return result
456
457
458def make_cpptoc_function_impl(cls, funcs, existing, prefixname, defined_names,
459                              base_scoped):
460  impl = ''
461
462  for func in funcs:
463    if not prefixname is None:
464      name = prefixname + '_' + func.get_capi_name()
465    else:
466      name = func.get_capi_name()
467    value = get_next_function_impl(existing, name)
468    if not value is None \
469        and value['body'].find('// AUTO-GENERATED CONTENT') < 0:
470      # an implementation exists that was not auto-generated
471      impl += make_cpptoc_function_impl_existing(cls, name, func, value,
472                                                 defined_names)
473    else:
474      impl += make_cpptoc_function_impl_new(cls, name, func, defined_names,
475                                            base_scoped)
476
477  return impl
478
479
480def make_cpptoc_virtual_function_impl(header, cls, existing, prefixname,
481                                      defined_names, base_scoped):
482  funcs = []
483  funcs.extend(cls.get_virtual_funcs())
484  cur_cls = cls
485  while True:
486    parent_name = cur_cls.get_parent_name()
487    if is_base_class(parent_name):
488      break
489    else:
490      parent_cls = header.get_class(parent_name, defined_names)
491      if parent_cls is None:
492        raise Exception('Class does not exist: ' + parent_name)
493      funcs.extend(parent_cls.get_virtual_funcs())
494    cur_cls = header.get_class(parent_name, defined_names)
495
496  return make_cpptoc_function_impl(cls, funcs, existing, prefixname,
497                                   defined_names, base_scoped)
498
499
500def make_cpptoc_virtual_function_assignment_block(funcs, offset, prefixname):
501  impl = ''
502  for func in funcs:
503    name = func.get_capi_name()
504    impl += '  GetStruct()->' + offset + name + ' = ' + prefixname + '_' + name + ';\n'
505  return impl
506
507
508def make_cpptoc_virtual_function_assignment(header, cls, prefixname,
509                                            defined_names):
510  impl = make_cpptoc_virtual_function_assignment_block(cls.get_virtual_funcs(),
511                                                       '', prefixname)
512
513  cur_cls = cls
514  offset = ''
515  while True:
516    parent_name = cur_cls.get_parent_name()
517    offset += 'base.'
518    if is_base_class(parent_name):
519      break
520    else:
521      parent_cls = header.get_class(parent_name, defined_names)
522      if parent_cls is None:
523        raise Exception('Class does not exist: ' + parent_name)
524      impl += make_cpptoc_virtual_function_assignment_block(
525          parent_cls.get_virtual_funcs(), offset, prefixname)
526    cur_cls = header.get_class(parent_name, defined_names)
527
528  return impl
529
530
531def make_cpptoc_unwrap_derived(header, cls, base_scoped):
532  # identify all classes that derive from cls
533  derived_classes = []
534  cur_clsname = cls.get_name()
535  allclasses = header.get_classes()
536  for cur_cls in allclasses:
537    if cur_cls.get_name() == cur_clsname:
538      continue
539    if cur_cls.has_parent(cur_clsname):
540      derived_classes.append(cur_cls.get_name())
541
542  derived_classes = sorted(derived_classes)
543
544  if base_scoped:
545    impl = ['', '']
546    for clsname in derived_classes:
547      impl[0] += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
548                 '    return '+clsname+'CppToC::UnwrapOwn(reinterpret_cast<'+\
549                 get_capi_name(clsname, True)+'*>(s));\n'+\
550                 '  }\n'
551      impl[1] += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
552                 '    return '+clsname+'CppToC::UnwrapRaw(reinterpret_cast<'+\
553                 get_capi_name(clsname, True)+'*>(s));\n'+\
554                 '  }\n'
555  else:
556    impl = ''
557    for clsname in derived_classes:
558      impl += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
559              '    return '+clsname+'CppToC::Unwrap(reinterpret_cast<'+\
560              get_capi_name(clsname, True)+'*>(s));\n'+\
561              '  }\n'
562  return impl
563
564
565def make_cpptoc_class_impl(header, clsname, impl):
566  # structure names that have already been defined
567  defined_names = header.get_defined_structs()
568
569  # retrieve the class and populate the defined names
570  cls = header.get_class(clsname, defined_names)
571  if cls is None:
572    raise Exception('Class does not exist: ' + clsname)
573
574  capiname = cls.get_capi_name()
575  prefixname = get_capi_name(clsname[3:], False)
576
577  # retrieve the existing virtual function implementations
578  existing = get_function_impls(impl, 'CEF_CALLBACK')
579
580  base_class_name = header.get_base_class_name(clsname)
581  base_scoped = True if base_class_name == 'CefBaseScoped' else False
582  if base_scoped:
583    template_class = 'CefCppToCScoped'
584  else:
585    template_class = 'CefCppToCRefCounted'
586
587  # generate virtual functions
588  virtualimpl = make_cpptoc_virtual_function_impl(
589      header, cls, existing, prefixname, defined_names, base_scoped)
590  if len(virtualimpl) > 0:
591    virtualimpl = '\nnamespace {\n\n// MEMBER FUNCTIONS - Body may be edited by hand.\n\n' + virtualimpl + '}  // namespace'
592
593  # the current class is already defined for static functions
594  defined_names.append(cls.get_capi_name())
595
596  # retrieve the existing static function implementations
597  existing = get_function_impls(impl, 'CEF_EXPORT')
598
599  # generate static functions
600  staticimpl = make_cpptoc_function_impl(cls,
601                                         cls.get_static_funcs(), existing, None,
602                                         defined_names, base_scoped)
603  if len(staticimpl) > 0:
604    staticimpl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n' + staticimpl
605
606  resultingimpl = staticimpl + virtualimpl
607
608  # any derived classes can be unwrapped
609  unwrapderived = make_cpptoc_unwrap_derived(header, cls, base_scoped)
610
611  const =  '// CONSTRUCTOR - Do not edit by hand.\n\n'+ \
612           clsname+'CppToC::'+clsname+'CppToC() {\n'
613  const += make_cpptoc_virtual_function_assignment(header, cls, prefixname,
614                                                   defined_names)
615  const += '}\n\n'+ \
616           '// DESTRUCTOR - Do not edit by hand.\n\n'+ \
617           clsname+'CppToC::~'+clsname+'CppToC() {\n'
618
619  if not cls.has_attrib('no_debugct_check') and not base_scoped:
620    const += '  shutdown_checker::AssertNotShutdown();\n'
621
622  const += '}\n\n'
623
624  # determine what includes are required by identifying what translation
625  # classes are being used
626  includes = format_translation_includes(header, const + resultingimpl +
627                                         (unwrapderived[0]
628                                          if base_scoped else unwrapderived))
629
630  # build the final output
631  result = get_copyright()
632
633  result += includes + '\n' + resultingimpl + '\n'
634
635  parent_sig = template_class + '<' + clsname + 'CppToC, ' + clsname + ', ' + capiname + '>'
636
637  if base_scoped:
638    const += 'template<> CefOwnPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, '+capiname+'* s) {\n' + \
639             unwrapderived[0] + \
640             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
641             '  return CefOwnPtr<'+clsname+'>();\n'+ \
642             '}\n\n' + \
643             'template<> CefRawPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, '+capiname+'* s) {\n' + \
644             unwrapderived[1] + \
645             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
646             '  return nullptr;\n'+ \
647             '}\n\n'
648  else:
649    const += 'template<> CefRefPtr<'+clsname+'> '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+capiname+'* s) {\n' + \
650             unwrapderived + \
651             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
652             '  return nullptr;\n'+ \
653             '}\n\n'
654
655  const += 'template<> CefWrapperType ' + parent_sig + '::kWrapperType = ' + get_wrapper_type_enum(
656      clsname) + ';'
657
658  result += '\n\n' + const
659
660  return result
661
662
663def make_cpptoc_global_impl(header, impl):
664  # structure names that have already been defined
665  defined_names = header.get_defined_structs()
666
667  # retrieve the existing global function implementations
668  existing = get_function_impls(impl, 'CEF_EXPORT')
669
670  # generate global functions
671  impl = make_cpptoc_function_impl(None,
672                                   header.get_funcs(), existing, None,
673                                   defined_names, False)
674  if len(impl) > 0:
675    impl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n' + impl
676
677  includes = ''
678
679  # include required headers for global functions
680  filenames = []
681  for func in header.get_funcs():
682    filename = func.get_file_name()
683    if not filename in filenames:
684      includes += '#include "include/'+func.get_file_name()+'"\n' \
685                  '#include "include/capi/'+func.get_capi_file_name()+'"\n'
686      filenames.append(filename)
687
688  # determine what includes are required by identifying what translation
689  # classes are being used
690  includes += format_translation_includes(header, impl)
691
692  # build the final output
693  result = get_copyright()
694
695  result += includes + '\n' + impl
696
697  return result
698
699
700def write_cpptoc_impl(header, clsname, dir):
701  if clsname is None:
702    # global file
703    file = dir
704  else:
705    # class file
706    # give the output file the same directory offset as the input file
707    cls = header.get_class(clsname)
708    dir = os.path.dirname(os.path.join(dir, cls.get_file_name()))
709    file = os.path.join(dir, get_capi_name(clsname[3:], False) + '_cpptoc.cc')
710
711  if path_exists(file):
712    oldcontents = read_file(file)
713  else:
714    oldcontents = ''
715
716  if clsname is None:
717    newcontents = make_cpptoc_global_impl(header, oldcontents)
718  else:
719    newcontents = make_cpptoc_class_impl(header, clsname, oldcontents)
720  return (file, newcontents)
721
722
723# test the module
724if __name__ == "__main__":
725  import sys
726
727  # verify that the correct number of command-line arguments are provided
728  if len(sys.argv) < 4:
729    sys.stderr.write('Usage: ' + sys.argv[0] +
730                     ' <infile> <classname> <existing_impl>')
731    sys.exit()
732
733  # create the header object
734  header = obj_header()
735  header.add_file(sys.argv[1])
736
737  # read the existing implementation file into memory
738  try:
739    with open(sys.argv[3], 'r') as f:
740      data = f.read()
741  except IOError as e:
742    (errno, strerror) = e.args
743    raise Exception('Failed to read file ' + sys.argv[3] + ': ' + strerror)
744  else:
745    f.close()
746
747  # dump the result to stdout
748  sys.stdout.write(make_cpptoc_class_impl(header, sys.argv[2], data))
749