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