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