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(OWN_PASS(' + arg_name + '))') 211 elif arg_type == 'rawptr_same': 212 ptr_class = arg.get_type().get_ptr_type() 213 params.append(ptr_class + 'CToCpp::UnwrapRaw(' + arg_name + ')') 214 elif arg_type == 'refptr_diff': 215 ptr_class = arg.get_type().get_ptr_type() 216 params.append(ptr_class + 'CppToC::Wrap(' + arg_name + ')') 217 elif arg_type == 'ownptr_diff': 218 ptr_class = arg.get_type().get_ptr_type() 219 params.append(ptr_class + 'CppToC::WrapOwn(OWN_PASS(' + arg_name + '))') 220 elif arg_type == 'rawptr_diff': 221 ptr_class = arg.get_type().get_ptr_type() 222 result += comment+\ 223 '\n CefOwnPtr<'+ptr_class+'CppToC> '+arg_name+'Ptr('+ptr_class+'CppToC::WrapRaw('+arg_name+'));' 224 params.append(arg_name + 'Ptr->GetStruct()') 225 elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': 226 ptr_class = arg.get_type().get_ptr_type() 227 ptr_struct = arg.get_type().get_result_ptr_type_root() 228 if arg_type == 'refptr_same_byref': 229 assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + ')' 230 else: 231 assign = ptr_class + 'CppToC::Wrap(' + arg_name + ')' 232 result += comment+\ 233 '\n '+ptr_struct+'* '+arg_name+'Struct = NULL;'\ 234 '\n if ('+arg_name+'.get())'\ 235 '\n '+arg_name+'Struct = '+assign+';'\ 236 '\n '+ptr_struct+'* '+arg_name+'Orig = '+arg_name+'Struct;' 237 params.append('&' + arg_name + 'Struct') 238 elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const': 239 result += comment+\ 240 '\n cef_string_list_t '+arg_name+'List = cef_string_list_alloc();'\ 241 '\n DCHECK('+arg_name+'List);'\ 242 '\n if ('+arg_name+'List)'\ 243 '\n transfer_string_list_contents('+arg_name+', '+arg_name+'List);' 244 params.append(arg_name + 'List') 245 elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const': 246 result += comment+\ 247 '\n cef_string_map_t '+arg_name+'Map = cef_string_map_alloc();'\ 248 '\n DCHECK('+arg_name+'Map);'\ 249 '\n if ('+arg_name+'Map)'\ 250 '\n transfer_string_map_contents('+arg_name+', '+arg_name+'Map);' 251 params.append(arg_name + 'Map') 252 elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const': 253 result += comment+\ 254 '\n cef_string_multimap_t '+arg_name+'Multimap = cef_string_multimap_alloc();'\ 255 '\n DCHECK('+arg_name+'Multimap);'\ 256 '\n if ('+arg_name+'Multimap)'\ 257 '\n transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);' 258 params.append(arg_name + 'Multimap') 259 elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ 260 arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': 261 count_func = arg.get_attrib_count_func() 262 vec_type = arg.get_type().get_result_vector_type_root() 263 if arg_type == 'refptr_vec_same_byref': 264 ptr_class = arg.get_type().get_ptr_type() 265 assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + '[i])' 266 elif arg_type == 'refptr_vec_diff_byref': 267 ptr_class = arg.get_type().get_ptr_type() 268 assign = ptr_class + 'CppToC::Wrap(' + arg_name + '[i])' 269 else: 270 assign = arg_name + '[i]' 271 result += comment+\ 272 '\n size_t '+arg_name+'Size = '+arg_name+'.size();'\ 273 '\n size_t '+arg_name+'Count = std::max('+count_func+'(), '+arg_name+'Size);'\ 274 '\n '+vec_type+'* '+arg_name+'List = NULL;'\ 275 '\n if ('+arg_name+'Count > 0) {'\ 276 '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ 277 '\n DCHECK('+arg_name+'List);'\ 278 '\n if ('+arg_name+'List) {'\ 279 '\n memset('+arg_name+'List, 0, sizeof('+vec_type+')*'+arg_name+'Count);'\ 280 '\n }'\ 281 '\n if ('+arg_name+'List && '+arg_name+'Size > 0) {'\ 282 '\n for (size_t i = 0; i < '+arg_name+'Size; ++i) {'\ 283 '\n '+arg_name+'List[i] = '+assign+';'\ 284 '\n }'\ 285 '\n }'\ 286 '\n }' 287 params.append('&' + arg_name + 'Count') 288 params.append(arg_name + 'List') 289 elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ 290 arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \ 291 arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const': 292 count_func = arg.get_attrib_count_func() 293 vec_type = arg.get_type().get_result_vector_type_root() 294 if arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const': 295 assign = arg_name + '[i]' 296 else: 297 ptr_class = arg.get_type().get_ptr_type() 298 if arg_type == 'refptr_vec_same_byref_const': 299 assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + '[i])' 300 elif arg_type == 'refptr_vec_diff_byref_const': 301 assign = ptr_class + 'CppToC::Wrap(' + arg_name + '[i])' 302 elif arg_type == 'rawptr_vec_same_byref_const': 303 assign = ptr_class + 'CToCpp::UnwrapRaw(' + arg_name + '[i])' 304 elif arg_type == 'rawptr_vec_diff_byref_const': 305 assign = ptr_class + 'CppToC::WrapRaw(' + arg_name + '[i]).release()->GetStruct()' 306 result += comment+\ 307 '\n const size_t '+arg_name+'Count = '+arg_name+'.size();'\ 308 '\n '+vec_type+'* '+arg_name+'List = NULL;'\ 309 '\n if ('+arg_name+'Count > 0) {'\ 310 '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ 311 '\n DCHECK('+arg_name+'List);'\ 312 '\n if ('+arg_name+'List) {'\ 313 '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ 314 '\n '+arg_name+'List[i] = '+assign+';'\ 315 '\n }'\ 316 '\n }'\ 317 '\n }' 318 params.append(arg_name + 'Count') 319 params.append(arg_name + 'List') 320 else: 321 raise Exception('Unsupported argument type %s for parameter %s in %s' % 322 (arg_type, arg_name, name)) 323 324 if len(result) != result_len: 325 result += '\n' 326 result_len = len(result) 327 328 if is_cef_shutdown: 329 result += '\n\n#if DCHECK_IS_ON()'\ 330 '\n shutdown_checker::SetIsShutdown();'\ 331 '\n#endif\n' 332 333 # execution 334 result += '\n // Execute\n ' 335 336 if retval_type != 'none': 337 # has a return value 338 if retval_type == 'simple' or retval_type == 'bool': 339 result += retval.get_type().get_result_simple_type_root() 340 elif retval_type == 'string': 341 result += 'cef_string_userfree_t' 342 elif retval_type == 'refptr_same' or retval_type == 'refptr_diff' or \ 343 retval_type == 'ownptr_same' or retval_type == 'ownptr_diff': 344 ptr_struct = retval.get_type().get_result_ptr_type_root() 345 result += ptr_struct + '*' 346 else: 347 raise Exception('Unsupported return type %s in %s' % (retval_type, name)) 348 349 result += ' _retval = ' 350 351 if isinstance(func, obj_function_virtual): 352 result += '_struct->' 353 result += func.get_capi_name() + '(' 354 355 if len(params) > 0: 356 if not isinstance(func, obj_function_virtual): 357 result += '\n ' 358 result += ',\n '.join(params) 359 360 result += ');\n' 361 362 result_len = len(result) 363 364 # parameter restoration 365 for arg in args: 366 arg_type = arg.get_arg_type() 367 arg_name = arg.get_type().get_name() 368 369 comment = '\n // Restore param:' + arg_name + '; type: ' + arg_type 370 371 if arg_type == 'bool_byref': 372 result += comment+\ 373 '\n '+arg_name+' = '+arg_name+'Int?true:false;' 374 elif arg_type == 'bool_byaddr': 375 result += comment+\ 376 '\n if ('+arg_name+')'\ 377 '\n *'+arg_name+' = '+arg_name+'Int?true:false;' 378 elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': 379 ptr_class = arg.get_type().get_ptr_type() 380 ptr_struct = arg.get_type().get_result_ptr_type_root() 381 if arg_type == 'refptr_same_byref': 382 assign = ptr_class + 'CToCpp::Wrap(' + arg_name + 'Struct)' 383 else: 384 assign = ptr_class + 'CppToC::Unwrap(' + arg_name + 'Struct)' 385 result += comment+\ 386 '\n if ('+arg_name+'Struct) {'\ 387 '\n if ('+arg_name+'Struct != '+arg_name+'Orig) {'\ 388 '\n '+arg_name+' = '+assign+';'\ 389 '\n }'\ 390 '\n } else {'\ 391 '\n '+arg_name+' = nullptr;'\ 392 '\n }' 393 elif arg_type == 'string_vec_byref': 394 result += comment+\ 395 '\n if ('+arg_name+'List) {'\ 396 '\n '+arg_name+'.clear();'\ 397 '\n transfer_string_list_contents('+arg_name+'List, '+arg_name+');'\ 398 '\n cef_string_list_free('+arg_name+'List);'\ 399 '\n }' 400 elif arg_type == 'string_vec_byref_const': 401 result += comment+\ 402 '\n if ('+arg_name+'List)'\ 403 '\n cef_string_list_free('+arg_name+'List);' 404 elif arg_type == 'string_map_single_byref': 405 result += comment+\ 406 '\n if ('+arg_name+'Map) {'\ 407 '\n '+arg_name+'.clear();'\ 408 '\n transfer_string_map_contents('+arg_name+'Map, '+arg_name+');'\ 409 '\n cef_string_map_free('+arg_name+'Map);'\ 410 '\n }' 411 elif arg_type == 'string_map_single_byref_const': 412 result += comment+\ 413 '\n if ('+arg_name+'Map)'\ 414 '\n cef_string_map_free('+arg_name+'Map);' 415 elif arg_type == 'string_map_multi_byref': 416 result += comment+\ 417 '\n if ('+arg_name+'Multimap) {'\ 418 '\n '+arg_name+'.clear();'\ 419 '\n transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');'\ 420 '\n cef_string_multimap_free('+arg_name+'Multimap);'\ 421 '\n }' 422 elif arg_type == 'string_map_multi_byref_const': 423 result += comment+\ 424 '\n if ('+arg_name+'Multimap)'\ 425 '\n cef_string_multimap_free('+arg_name+'Multimap);' 426 elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ 427 arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': 428 count_func = arg.get_attrib_count_func() 429 vec_type = arg.get_type().get_result_vector_type_root() 430 if arg_type == 'refptr_vec_same_byref': 431 ptr_class = arg.get_type().get_ptr_type() 432 assign = ptr_class + 'CToCpp::Wrap(' + arg_name + 'List[i])' 433 elif arg_type == 'refptr_vec_diff_byref': 434 ptr_class = arg.get_type().get_ptr_type() 435 assign = ptr_class + 'CppToC::Unwrap(' + arg_name + 'List[i])' 436 elif arg_type == 'bool_vec_byref': 437 assign = arg_name + 'List[i]?true:false' 438 else: 439 assign = arg_name + 'List[i]' 440 result += comment+\ 441 '\n '+arg_name+'.clear();'\ 442 '\n if ('+arg_name+'Count > 0 && '+arg_name+'List) {'\ 443 '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ 444 '\n '+arg_name+'.push_back('+assign+');'\ 445 '\n }'\ 446 '\n delete [] '+arg_name+'List;'\ 447 '\n }' 448 elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ 449 arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \ 450 arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const': 451 result += comment 452 if arg_type == 'rawptr_vec_diff_byref_const': 453 result += '\n if ('+arg_name+'Count > 0) {'\ 454 '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ 455 '\n delete '+ptr_class+'CppToC::GetWrapper('+arg_name+'List[i]);'\ 456 '\n }'\ 457 '\n }' 458 result += '\n if ('+arg_name+'List)'\ 459 '\n delete [] '+arg_name+'List;' 460 461 if len(result) != result_len: 462 result += '\n' 463 result_len = len(result) 464 465 if len(result) != result_len: 466 result += '\n' 467 result_len = len(result) 468 469 # return translation 470 if retval_type != 'none': 471 # has a return value 472 result += '\n // Return type: ' + retval_type 473 if retval_type == 'simple': 474 result += '\n return _retval;' 475 elif retval_type == 'bool': 476 result += '\n return _retval?true:false;' 477 elif retval_type == 'string': 478 result += '\n CefString _retvalStr;'\ 479 '\n _retvalStr.AttachToUserFree(_retval);'\ 480 '\n return _retvalStr;' 481 elif retval_type == 'refptr_same' or retval_type == 'ownptr_same': 482 ptr_class = retval.get_type().get_ptr_type() 483 result += '\n return ' + ptr_class + 'CToCpp::Wrap(_retval);' 484 elif retval_type == 'refptr_diff': 485 ptr_class = retval.get_type().get_ptr_type() 486 result += '\n return ' + ptr_class + 'CppToC::Unwrap(_retval);' 487 elif retval_type == 'ownptr_diff': 488 ptr_class = retval.get_type().get_ptr_type() 489 result += '\n return ' + ptr_class + 'CppToC::UnwrapOwn(_retval);' 490 else: 491 raise Exception('Unsupported return type %s in %s' % (retval_type, name)) 492 493 if len(result) != result_len: 494 result += '\n' 495 496 result += '}\n\n' 497 return result 498 499 500def make_ctocpp_function_impl(clsname, funcs, existing, base_scoped): 501 impl = '' 502 503 for func in funcs: 504 name = func.get_name() 505 value = get_next_function_impl(existing, name) 506 if not value is None \ 507 and value['body'].find('// AUTO-GENERATED CONTENT') < 0: 508 # an implementation exists that was not auto-generated 509 impl += make_ctocpp_function_impl_existing(clsname, name, func, value) 510 else: 511 impl += make_ctocpp_function_impl_new(clsname, name, func, base_scoped) 512 513 return impl 514 515 516def make_ctocpp_virtual_function_impl(header, cls, existing, base_scoped): 517 impl = make_ctocpp_function_impl(cls.get_name(), 518 cls.get_virtual_funcs(), existing, 519 base_scoped) 520 521 cur_cls = cls 522 while True: 523 parent_name = cur_cls.get_parent_name() 524 if is_base_class(parent_name): 525 break 526 else: 527 parent_cls = header.get_class(parent_name) 528 if parent_cls is None: 529 raise Exception('Class does not exist: ' + parent_name) 530 impl += make_ctocpp_function_impl(cls.get_name(), 531 parent_cls.get_virtual_funcs(), 532 existing, base_scoped) 533 cur_cls = header.get_class(parent_name) 534 535 return impl 536 537 538def make_ctocpp_unwrap_derived(header, cls, base_scoped): 539 # identify all classes that derive from cls 540 derived_classes = [] 541 clsname = cls.get_name() 542 allclasses = header.get_classes() 543 for cur_cls in allclasses: 544 if cur_cls.get_name() == clsname: 545 continue 546 if cur_cls.has_parent(clsname): 547 derived_classes.append(cur_cls.get_name()) 548 549 derived_classes = sorted(derived_classes) 550 551 if base_scoped: 552 impl = ['', ''] 553 for clsname in derived_classes: 554 impl[0] += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\ 555 ' return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ 556 clsname+'CToCpp::UnwrapOwn(CefOwnPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(c.release()))));\n'+\ 557 ' }\n' 558 impl[1] += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\ 559 ' return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ 560 clsname+'CToCpp::UnwrapRaw(CefRawPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(CEF_RAW_PTR_GET(c)))));\n'+\ 561 ' }\n' 562 else: 563 impl = '' 564 for clsname in derived_classes: 565 impl += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\ 566 ' return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ 567 clsname+'CToCpp::Unwrap(reinterpret_cast<'+clsname+'*>(c)));\n'+\ 568 ' }\n' 569 return impl 570 571 572def make_ctocpp_class_impl(header, clsname, impl): 573 cls = header.get_class(clsname) 574 if cls is None: 575 raise Exception('Class does not exist: ' + clsname) 576 577 capiname = cls.get_capi_name() 578 579 # retrieve the existing virtual function implementations 580 existing = get_function_impls(impl, clsname + 'CToCpp::') 581 582 base_class_name = header.get_base_class_name(clsname) 583 base_scoped = True if base_class_name == 'CefBaseScoped' else False 584 if base_scoped: 585 template_class = 'CefCToCppScoped' 586 else: 587 template_class = 'CefCToCppRefCounted' 588 589 # generate virtual functions 590 virtualimpl = make_ctocpp_virtual_function_impl(header, cls, existing, 591 base_scoped) 592 if len(virtualimpl) > 0: 593 virtualimpl = '\n// VIRTUAL METHODS - Body may be edited by hand.\n\n' + virtualimpl 594 595 # retrieve the existing static function implementations 596 existing = get_function_impls(impl, clsname + '::') 597 598 # generate static functions 599 staticimpl = make_ctocpp_function_impl(clsname, 600 cls.get_static_funcs(), existing, 601 base_scoped) 602 if len(staticimpl) > 0: 603 staticimpl = '\n// STATIC METHODS - Body may be edited by hand.\n\n' + staticimpl 604 605 resultingimpl = staticimpl + virtualimpl 606 607 # any derived classes can be unwrapped 608 unwrapderived = make_ctocpp_unwrap_derived(header, cls, base_scoped) 609 610 const = '// CONSTRUCTOR - Do not edit by hand.\n\n'+ \ 611 clsname+'CToCpp::'+clsname+'CToCpp() {\n'+ \ 612 '}\n\n'+ \ 613 '// DESTRUCTOR - Do not edit by hand.\n\n'+ \ 614 clsname+'CToCpp::~'+clsname+'CToCpp() {\n' 615 616 if not cls.has_attrib('no_debugct_check') and not base_scoped: 617 const += ' shutdown_checker::AssertNotShutdown();\n' 618 619 const += '}\n\n' 620 621 # determine what includes are required by identifying what translation 622 # classes are being used 623 includes = format_translation_includes(header, const + resultingimpl + 624 (unwrapderived[0] 625 if base_scoped else unwrapderived)) 626 627 # build the final output 628 result = get_copyright() 629 630 result += includes + '\n' + resultingimpl + '\n' 631 632 parent_sig = template_class + '<' + clsname + 'CToCpp, ' + clsname + ', ' + capiname + '>' 633 634 if base_scoped: 635 const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, CefOwnPtr<'+clsname+'> c) {\n'+ \ 636 unwrapderived[0] + \ 637 ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \ 638 ' return nullptr;\n'+ \ 639 '}\n\n' + \ 640 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, CefRawPtr<'+clsname+'> c) {\n'+ \ 641 unwrapderived[1] + \ 642 ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \ 643 ' return nullptr;\n'+ \ 644 '}\n\n' 645 else: 646 const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+clsname+'* c) {\n'+ \ 647 unwrapderived + \ 648 ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \ 649 ' return nullptr;\n'+ \ 650 '}\n\n' 651 652 const += 'template<> CefWrapperType ' + parent_sig + '::kWrapperType = ' + get_wrapper_type_enum( 653 clsname) + ';' 654 655 result += const 656 657 return result 658 659 660def make_ctocpp_global_impl(header, impl): 661 # retrieve the existing global function implementations 662 existing = get_function_impls(impl, 'CEF_GLOBAL') 663 664 # generate static functions 665 impl = make_ctocpp_function_impl(None, header.get_funcs(), existing, False) 666 if len(impl) > 0: 667 impl = '\n// GLOBAL METHODS - Body may be edited by hand.\n\n' + impl 668 669 includes = '' 670 671 # include required headers for global functions 672 filenames = [] 673 for func in header.get_funcs(): 674 filename = func.get_file_name() 675 if not filename in filenames: 676 includes += '#include "include/'+func.get_file_name()+'"\n' \ 677 '#include "include/capi/'+func.get_capi_file_name()+'"\n' 678 filenames.append(filename) 679 680 # determine what includes are required by identifying what translation 681 # classes are being used 682 includes += format_translation_includes(header, impl) 683 684 # build the final output 685 result = get_copyright() 686 687 result += includes + '\n// Define used to facilitate parsing.\n#define CEF_GLOBAL\n\n' + impl 688 689 return result 690 691 692def write_ctocpp_impl(header, clsname, dir): 693 if clsname is None: 694 # global file 695 file = dir 696 else: 697 # class file 698 # give the output file the same directory offset as the input file 699 cls = header.get_class(clsname) 700 dir = os.path.dirname(os.path.join(dir, cls.get_file_name())) 701 file = os.path.join(dir, get_capi_name(clsname[3:], False) + '_ctocpp.cc') 702 703 if path_exists(file): 704 oldcontents = read_file(file) 705 else: 706 oldcontents = '' 707 708 if clsname is None: 709 newcontents = make_ctocpp_global_impl(header, oldcontents) 710 else: 711 newcontents = make_ctocpp_class_impl(header, clsname, oldcontents) 712 return (file, newcontents) 713 714 715# test the module 716if __name__ == "__main__": 717 import sys 718 719 # verify that the correct number of command-line arguments are provided 720 if len(sys.argv) < 4: 721 sys.stderr.write('Usage: ' + sys.argv[0] + 722 ' <infile> <classname> <existing_impl>\n') 723 sys.exit() 724 725 # create the header object 726 header = obj_header() 727 header.add_file(sys.argv[1]) 728 729 # read the existing implementation file into memory 730 try: 731 with open(sys.argv[3], 'r') as f: 732 data = f.read() 733 except IOError as e: 734 (errno, strerror) = e.args 735 raise Exception('Failed to read file ' + sys.argv[3] + ': ' + strerror) 736 737 # dump the result to stdout 738 sys.stdout.write(make_ctocpp_class_impl(header, sys.argv[2], data)) 739