1/* ----------------------------------------------------------------------------- 2 * See the LICENSE file for information on copyright, usage and redistribution 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. 4 * 5 * typeobj.c 6 * 7 * This file provides functions for constructing, manipulating, and testing 8 * type objects. Type objects are merely the raw low-level representation 9 * of C++ types. They do not incorporate high-level type system features 10 * like typedef, namespaces, etc. 11 * ----------------------------------------------------------------------------- */ 12 13char cvsroot_typeobj_c[] = "$Id: typeobj.c 11080 2009-01-24 13:15:51Z bhy $"; 14 15#include "swig.h" 16#include <ctype.h> 17 18/* ----------------------------------------------------------------------------- 19 * Synopsis 20 * 21 * This file provides a collection of low-level functions for constructing and 22 * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple 23 * text strings. This representation is compact, easy to debug, and easy to read. 24 * 25 * General idea: 26 * 27 * Types are represented by a base type (e.g., "int") and a collection of 28 * type operators applied to the base (e.g., pointers, arrays, etc...). 29 * 30 * Encoding: 31 * 32 * Types are encoded as strings of type constructors such as follows: 33 * 34 * String Encoding C Example 35 * --------------- --------- 36 * p.p.int int ** 37 * a(300).a(400).int int [300][400] 38 * p.q(const).char char const * 39 * 40 * All type constructors are denoted by a trailing '.': 41 * 42 * 'p.' = Pointer (*) 43 * 'r.' = Reference (&) 44 * 'a(n).' = Array of size n [n] 45 * 'f(..,..).' = Function with arguments (args) 46 * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) 47 * 'm(qual).' = Pointer to member (qual::*) 48 * 49 * The encoding follows the order that you might describe a type in words. 50 * For example "p.a(200).int" is "A pointer to array of int's" and 51 * "p.q(const).char" is "a pointer to a const char". 52 * 53 * This representation of types is fairly convenient because ordinary string 54 * operations can be used for type manipulation. For example, a type could be 55 * formed by combining two strings such as the following: 56 * 57 * "p.p." + "a(400).int" = "p.p.a(400).int" 58 * 59 * For C++, typenames may be parameterized using <(...)>. Here are some 60 * examples: 61 * 62 * String Encoding C++ Example 63 * --------------- ------------ 64 * p.vector<(int)> vector<int> * 65 * r.foo<(int,p.double)> foo<int,double *> & 66 * 67 * Contents of this file: 68 * 69 * Most of this functions in this file pertain to the low-level manipulation 70 * of type objects. There are constructor functions like this: 71 * 72 * SwigType_add_pointer() 73 * SwigType_add_reference() 74 * SwigType_add_array() 75 * 76 * These are used to build new types. There are also functions to undo these 77 * operations. For example: 78 * 79 * SwigType_del_pointer() 80 * SwigType_del_reference() 81 * SwigType_del_array() 82 * 83 * In addition, there are query functions 84 * 85 * SwigType_ispointer() 86 * SwigType_isreference() 87 * SwigType_isarray() 88 * 89 * Finally, there are some data extraction functions that can be used to 90 * extract array dimensions, template arguments, and so forth. 91 * 92 * It is very important for developers to realize that the functions in this 93 * module do *NOT* incorporate higher-level type system features like typedef. 94 * For example, you could have C code like this: 95 * 96 * typedef int *intptr; 97 * 98 * In this case, a SwigType of type 'intptr' will be treated as a simple type and 99 * functions like SwigType_ispointer() will evaluate as false. It is strongly 100 * advised that developers use the TypeSys_* interface to check types in a more 101 * reliable manner. 102 * ----------------------------------------------------------------------------- */ 103 104 105/* ----------------------------------------------------------------------------- 106 * NewSwigType() 107 * 108 * Constructs a new type object. Eventually, it would be nice for this function 109 * to accept an initial value in the form a C/C++ abstract type (currently unimplemented). 110 * ----------------------------------------------------------------------------- */ 111 112#ifdef NEW 113SwigType *NewSwigType(const_String_or_char_ptr initial) { 114 return NewString(initial); 115} 116 117#endif 118 119/* The next few functions are utility functions used in the construction and 120 management of types */ 121 122/* ----------------------------------------------------------------------------- 123 * static element_size() 124 * 125 * This utility function finds the size of a single type element in a type string. 126 * Type elements are always delimited by periods, but may be nested with 127 * parentheses. A nested element is always handled as a single item. 128 * 129 * Returns the integer size of the element (which can be used to extract a 130 * substring, to chop the element off, or for other purposes). 131 * ----------------------------------------------------------------------------- */ 132 133static int element_size(char *c) { 134 int nparen; 135 char *s = c; 136 while (*c) { 137 if (*c == '.') { 138 c++; 139 return (int) (c - s); 140 } else if (*c == '(') { 141 nparen = 1; 142 c++; 143 while (*c) { 144 if (*c == '(') 145 nparen++; 146 if (*c == ')') { 147 nparen--; 148 if (nparen == 0) 149 break; 150 } 151 c++; 152 } 153 } 154 if (*c) 155 c++; 156 } 157 return (int) (c - s); 158} 159 160/* ----------------------------------------------------------------------------- 161 * SwigType_del_element() 162 * 163 * Deletes one type element from the type. 164 * ----------------------------------------------------------------------------- */ 165 166SwigType *SwigType_del_element(SwigType *t) { 167 int sz = element_size(Char(t)); 168 Delslice(t, 0, sz); 169 return t; 170} 171 172/* ----------------------------------------------------------------------------- 173 * SwigType_pop() 174 * 175 * Pop one type element off the type. 176 * ----------------------------------------------------------------------------- */ 177 178SwigType *SwigType_pop(SwigType *t) { 179 SwigType *result; 180 char *c; 181 int sz; 182 183 c = Char(t); 184 if (!*c) 185 return 0; 186 187 sz = element_size(c); 188 result = NewStringWithSize(c, sz); 189 Delslice(t, 0, sz); 190 c = Char(t); 191 if (*c == '.') { 192 Delitem(t, 0); 193 } 194 return result; 195} 196 197/* ----------------------------------------------------------------------------- 198 * SwigType_parm() 199 * 200 * Returns the parameter of an operator as a string 201 * ----------------------------------------------------------------------------- */ 202 203String *SwigType_parm(SwigType *t) { 204 char *start, *c; 205 int nparens = 0; 206 207 c = Char(t); 208 while (*c && (*c != '(') && (*c != '.')) 209 c++; 210 if (!*c || (*c == '.')) 211 return 0; 212 c++; 213 start = c; 214 while (*c) { 215 if (*c == ')') { 216 if (nparens == 0) 217 break; 218 nparens--; 219 } else if (*c == '(') { 220 nparens++; 221 } 222 c++; 223 } 224 return NewStringWithSize(start, (int) (c - start)); 225} 226 227/* ----------------------------------------------------------------------------- 228 * SwigType_split() 229 * 230 * Splits a type into it's component parts and returns a list of string. 231 * ----------------------------------------------------------------------------- */ 232 233List *SwigType_split(const SwigType *t) { 234 String *item; 235 List *list; 236 char *c; 237 int len; 238 239 c = Char(t); 240 list = NewList(); 241 while (*c) { 242 len = element_size(c); 243 item = NewStringWithSize(c, len); 244 Append(list, item); 245 Delete(item); 246 c = c + len; 247 if (*c == '.') 248 c++; 249 } 250 return list; 251} 252 253/* ----------------------------------------------------------------------------- 254 * SwigType_parmlist() 255 * 256 * Splits a comma separated list of parameters into its component parts 257 * The input is expected to contain the parameter list within () brackets 258 * Returns 0 if no argument list in the input, ie there are no round brackets () 259 * Returns an empty List if there are no parameters in the () brackets 260 * For example: 261 * 262 * Foo(std::string,p.f().Bar<(int,double)>) 263 * 264 * returns 2 elements in the list: 265 * std::string 266 * p.f().Bar<(int,double)> 267 * ----------------------------------------------------------------------------- */ 268 269List *SwigType_parmlist(const String *p) { 270 String *item = 0; 271 List *list; 272 char *c; 273 char *itemstart; 274 int size; 275 276 assert(p); 277 c = Char(p); 278 while (*c && (*c != '(') && (*c != '.')) 279 c++; 280 if (!*c) 281 return 0; 282 assert(*c != '.'); /* p is expected to contain sub elements of a type */ 283 c++; 284 list = NewList(); 285 itemstart = c; 286 while (*c) { 287 if (*c == ',') { 288 size = (int) (c - itemstart); 289 item = NewStringWithSize(itemstart, size); 290 Append(list, item); 291 Delete(item); 292 itemstart = c + 1; 293 } else if (*c == '(') { 294 int nparens = 1; 295 c++; 296 while (*c) { 297 if (*c == '(') 298 nparens++; 299 if (*c == ')') { 300 nparens--; 301 if (nparens == 0) 302 break; 303 } 304 c++; 305 } 306 } else if (*c == ')') { 307 break; 308 } 309 if (*c) 310 c++; 311 } 312 size = (int) (c - itemstart); 313 if (size > 0) { 314 item = NewStringWithSize(itemstart, size); 315 Append(list, item); 316 } 317 Delete(item); 318 return list; 319} 320 321/* ----------------------------------------------------------------------------- 322 * Pointers 323 * 324 * SwigType_add_pointer() 325 * SwigType_del_pointer() 326 * SwigType_ispointer() 327 * 328 * Add, remove, and test if a type is a pointer. The deletion and query 329 * functions take into account qualifiers (if any). 330 * ----------------------------------------------------------------------------- */ 331 332SwigType *SwigType_add_pointer(SwigType *t) { 333 Insert(t, 0, "p."); 334 return t; 335} 336 337SwigType *SwigType_del_pointer(SwigType *t) { 338 char *c, *s; 339 c = Char(t); 340 s = c; 341 /* Skip qualifiers, if any */ 342 if (strncmp(c, "q(", 2) == 0) { 343 c = strchr(c, '.'); 344 assert(c); 345 c++; 346 } 347 if (strncmp(c, "p.", 2)) { 348 printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n"); 349 abort(); 350 } 351 Delslice(t, 0, (c - s) + 2); 352 return t; 353} 354 355int SwigType_ispointer(SwigType *t) { 356 char *c; 357 if (!t) 358 return 0; 359 c = Char(t); 360 /* Skip qualifiers, if any */ 361 if (strncmp(c, "q(", 2) == 0) { 362 c = strchr(c, '.'); 363 if (!c) 364 return 0; 365 c++; 366 } 367 if (strncmp(c, "p.", 2) == 0) { 368 return 1; 369 } 370 return 0; 371} 372 373/* ----------------------------------------------------------------------------- 374 * References 375 * 376 * SwigType_add_reference() 377 * SwigType_del_reference() 378 * SwigType_isreference() 379 * 380 * Add, remove, and test if a type is a reference. The deletion and query 381 * functions take into account qualifiers (if any). 382 * ----------------------------------------------------------------------------- */ 383 384SwigType *SwigType_add_reference(SwigType *t) { 385 Insert(t, 0, "r."); 386 return t; 387} 388 389SwigType *SwigType_del_reference(SwigType *t) { 390 char *c = Char(t); 391 int check = strncmp(c, "r.", 2); 392 assert(check == 0); 393 Delslice(t, 0, 2); 394 return t; 395} 396 397int SwigType_isreference(SwigType *t) { 398 char *c; 399 if (!t) 400 return 0; 401 c = Char(t); 402 if (strncmp(c, "r.", 2) == 0) { 403 return 1; 404 } 405 return 0; 406} 407 408/* ----------------------------------------------------------------------------- 409 * Qualifiers 410 * 411 * SwigType_add_qualifier() 412 * SwigType_del_qualifier() 413 * SwigType_is_qualifier() 414 * 415 * Adds type qualifiers like "const" and "volatile". When multiple qualifiers 416 * are added to a type, they are combined together into a single qualifier. 417 * Repeated qualifications have no effect. Moreover, the order of qualifications 418 * is alphabetical---meaning that "const volatile" and "volatile const" are 419 * stored in exactly the same way as "q(const volatile)". 420 * ----------------------------------------------------------------------------- */ 421 422SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) { 423 char temp[256], newq[256]; 424 int sz, added = 0; 425 char *q, *cqual; 426 427 char *c = Char(t); 428 cqual = Char(qual); 429 430 if (!(strncmp(c, "q(", 2) == 0)) { 431 sprintf(temp, "q(%s).", cqual); 432 Insert(t, 0, temp); 433 return t; 434 } 435 436 /* The type already has a qualifier on it. In this case, we first check to 437 see if the qualifier is already specified. In that case do nothing. 438 If it is a new qualifier, we add it to the qualifier list in alphabetical 439 order */ 440 441 sz = element_size(c); 442 strncpy(temp, c, (sz < 256) ? sz : 256); 443 444 if (strstr(temp, cqual)) { 445 /* Qualifier already added */ 446 return t; 447 } 448 449 /* Add the qualifier to the existing list. */ 450 451 strcpy(newq, "q("); 452 q = temp + 2; 453 q = strtok(q, " )."); 454 while (q) { 455 if (strcmp(cqual, q) < 0) { 456 /* New qualifier is less that current qualifier. We need to insert it */ 457 strcat(newq, cqual); 458 strcat(newq, " "); 459 strcat(newq, q); 460 added = 1; 461 } else { 462 strcat(newq, q); 463 } 464 q = strtok(NULL, " )."); 465 if (q) { 466 strcat(newq, " "); 467 } 468 } 469 if (!added) { 470 strcat(newq, " "); 471 strcat(newq, cqual); 472 } 473 strcat(newq, ")."); 474 Delslice(t, 0, sz); 475 Insert(t, 0, newq); 476 return t; 477} 478 479SwigType *SwigType_del_qualifier(SwigType *t) { 480 char *c = Char(t); 481 int check = strncmp(c, "q(", 2); 482 assert(check == 0); 483 Delslice(t, 0, element_size(c)); 484 return t; 485} 486 487int SwigType_isqualifier(SwigType *t) { 488 char *c; 489 if (!t) 490 return 0; 491 c = Char(t); 492 if (strncmp(c, "q(", 2) == 0) { 493 return 1; 494 } 495 return 0; 496} 497 498/* ----------------------------------------------------------------------------- 499 * Function Pointers 500 * ----------------------------------------------------------------------------- */ 501 502int SwigType_isfunctionpointer(SwigType *t) { 503 char *c; 504 if (!t) 505 return 0; 506 c = Char(t); 507 if (strncmp(c, "p.f(", 4) == 0) { 508 return 1; 509 } 510 return 0; 511} 512 513/* ----------------------------------------------------------------------------- 514 * SwigType_functionpointer_decompose 515 * 516 * Decompose the function pointer into the parameter list and the return type 517 * t - input and on completion contains the return type 518 * returns the function's parameters 519 * ----------------------------------------------------------------------------- */ 520 521SwigType *SwigType_functionpointer_decompose(SwigType *t) { 522 String *p; 523 assert(SwigType_isfunctionpointer(t)); 524 p = SwigType_pop(t); 525 Delete(p); 526 p = SwigType_pop(t); 527 return p; 528} 529 530/* ----------------------------------------------------------------------------- 531 * Member Pointers 532 * 533 * SwigType_add_memberpointer() 534 * SwigType_del_memberpointer() 535 * SwigType_ismemberpointer() 536 * 537 * Add, remove, and test for C++ pointer to members. 538 * ----------------------------------------------------------------------------- */ 539 540SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) { 541 String *temp = NewStringf("m(%s).", name); 542 Insert(t, 0, temp); 543 Delete(temp); 544 return t; 545} 546 547SwigType *SwigType_del_memberpointer(SwigType *t) { 548 char *c = Char(t); 549 int check = strncmp(c, "m(", 2); 550 assert(check == 0); 551 Delslice(t, 0, element_size(c)); 552 return t; 553} 554 555int SwigType_ismemberpointer(SwigType *t) { 556 char *c; 557 if (!t) 558 return 0; 559 c = Char(t); 560 if (strncmp(c, "m(", 2) == 0) { 561 return 1; 562 } 563 return 0; 564} 565 566/* ----------------------------------------------------------------------------- 567 * Arrays 568 * 569 * SwigType_add_array() 570 * SwigType_del_array() 571 * SwigType_isarray() 572 * 573 * Utility functions: 574 * 575 * SwigType_array_ndim() - Calculate number of array dimensions. 576 * SwigType_array_getdim() - Get array dimension 577 * SwigType_array_setdim() - Set array dimension 578 * SwigType_array_type() - Return array type 579 * SwigType_pop_arrays() - Remove all arrays 580 * ----------------------------------------------------------------------------- */ 581 582SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) { 583 char temp[512]; 584 strcpy(temp, "a("); 585 strcat(temp, Char(size)); 586 strcat(temp, ")."); 587 Insert(t, 0, temp); 588 return t; 589} 590 591SwigType *SwigType_del_array(SwigType *t) { 592 char *c = Char(t); 593 int check = strncmp(c, "a(", 2); 594 assert(check == 0); 595 Delslice(t, 0, element_size(c)); 596 return t; 597} 598 599int SwigType_isarray(SwigType *t) { 600 char *c; 601 if (!t) 602 return 0; 603 c = Char(t); 604 if (strncmp(c, "a(", 2) == 0) { 605 return 1; 606 } 607 return 0; 608} 609/* 610 * SwigType_prefix_is_simple_1D_array 611 * 612 * Determine if the type is a 1D array type that is treated as a pointer within SWIG 613 * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false 614 */ 615int SwigType_prefix_is_simple_1D_array(SwigType *t) { 616 char *c = Char(t); 617 618 if (c && (strncmp(c, "a(", 2) == 0)) { 619 c = strchr(c, '.'); 620 c++; 621 return (*c == 0); 622 } 623 return 0; 624} 625 626 627/* Remove all arrays */ 628SwigType *SwigType_pop_arrays(SwigType *t) { 629 String *ta; 630 assert(SwigType_isarray(t)); 631 ta = NewStringEmpty(); 632 while (SwigType_isarray(t)) { 633 SwigType *td = SwigType_pop(t); 634 Append(ta, td); 635 Delete(td); 636 } 637 return ta; 638} 639 640/* Return number of array dimensions */ 641int SwigType_array_ndim(SwigType *t) { 642 int ndim = 0; 643 char *c = Char(t); 644 645 while (c && (strncmp(c, "a(", 2) == 0)) { 646 c = strchr(c, '.'); 647 c++; 648 ndim++; 649 } 650 return ndim; 651} 652 653/* Get nth array dimension */ 654String *SwigType_array_getdim(SwigType *t, int n) { 655 char *c = Char(t); 656 while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) { 657 c = strchr(c, '.'); 658 c++; 659 n--; 660 } 661 if (n == 0) { 662 String *dim = SwigType_parm(c); 663 if (SwigType_istemplate(dim)) { 664 String *ndim = SwigType_namestr(dim); 665 Delete(dim); 666 dim = ndim; 667 } 668 669 return dim; 670 } 671 672 return 0; 673} 674 675/* Replace nth array dimension */ 676void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) { 677 String *result = 0; 678 char temp; 679 char *start; 680 char *c = Char(t); 681 682 start = c; 683 if (strncmp(c, "a(", 2)) 684 abort(); 685 686 while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) { 687 c = strchr(c, '.'); 688 c++; 689 n--; 690 } 691 if (n == 0) { 692 temp = *c; 693 *c = 0; 694 result = NewString(start); 695 Printf(result, "a(%s)", rep); 696 *c = temp; 697 c = strchr(c, '.'); 698 Append(result, c); 699 } 700 Clear(t); 701 Append(t, result); 702 Delete(result); 703} 704 705/* Return base type of an array */ 706SwigType *SwigType_array_type(SwigType *ty) { 707 SwigType *t; 708 t = Copy(ty); 709 while (SwigType_isarray(t)) { 710 Delete(SwigType_pop(t)); 711 } 712 return t; 713} 714 715 716/* ----------------------------------------------------------------------------- 717 * Functions 718 * 719 * SwigType_add_function() 720 * SwigType_del_function() 721 * SwigType_isfunction() 722 * SwigType_pop_function() 723 * 724 * Add, remove, and test for function types. 725 * ----------------------------------------------------------------------------- */ 726 727/* Returns the function type, t, constructed from the parameters, parms */ 728SwigType *SwigType_add_function(SwigType *t, ParmList *parms) { 729 String *pstr; 730 Parm *p; 731 732 Insert(t, 0, ")."); 733 pstr = NewString("f("); 734 p = parms; 735 for (p = parms; p; p = nextSibling(p)) { 736 if (p != parms) 737 Putc(',', pstr); 738 Append(pstr, Getattr(p, "type")); 739 } 740 Insert(t, 0, pstr); 741 Delete(pstr); 742 return t; 743} 744 745SwigType *SwigType_pop_function(SwigType *t) { 746 SwigType *f = 0; 747 SwigType *g = 0; 748 char *c = Char(t); 749 if (strncmp(c, "q(", 2) == 0) { 750 f = SwigType_pop(t); 751 c = Char(t); 752 } 753 if (strncmp(c, "f(", 2)) { 754 printf("Fatal error. SwigType_pop_function applied to non-function.\n"); 755 abort(); 756 } 757 g = SwigType_pop(t); 758 if (f) 759 SwigType_push(g, f); 760 Delete(f); 761 return g; 762} 763 764int SwigType_isfunction(SwigType *t) { 765 char *c; 766 if (!t) { 767 return 0; 768 } 769 c = Char(t); 770 if (strncmp(c, "q(", 2) == 0) { 771 /* Might be a 'const' function. Try to skip over the 'const' */ 772 c = strchr(c, '.'); 773 if (c) 774 c++; 775 else 776 return 0; 777 } 778 if (strncmp(c, "f(", 2) == 0) { 779 return 1; 780 } 781 return 0; 782} 783 784ParmList *SwigType_function_parms(SwigType *t) { 785 List *l = SwigType_parmlist(t); 786 Hash *p, *pp = 0, *firstp = 0; 787 Iterator o; 788 789 for (o = First(l); o.item; o = Next(o)) { 790 p = NewParm(o.item, 0); 791 if (!firstp) 792 firstp = p; 793 if (pp) { 794 set_nextSibling(pp, p); 795 Delete(p); 796 } 797 pp = p; 798 } 799 Delete(l); 800 return firstp; 801} 802 803int SwigType_isvarargs(const SwigType *t) { 804 if (Strcmp(t, "v(...)") == 0) 805 return 1; 806 return 0; 807} 808 809/* ----------------------------------------------------------------------------- 810 * Templates 811 * 812 * SwigType_add_template() 813 * 814 * Template handling. 815 * ----------------------------------------------------------------------------- */ 816 817/* ----------------------------------------------------------------------------- 818 * SwigType_add_template() 819 * 820 * Adds a template to a type. This template is encoded in the SWIG type 821 * mechanism and produces a string like this: 822 * 823 * vector<int *> ----> "vector<(p.int)>" 824 * ----------------------------------------------------------------------------- */ 825 826SwigType *SwigType_add_template(SwigType *t, ParmList *parms) { 827 Parm *p; 828 829 Append(t, "<("); 830 p = parms; 831 for (p = parms; p; p = nextSibling(p)) { 832 String *v; 833 if (Getattr(p, "default")) 834 continue; 835 if (p != parms) 836 Append(t, ","); 837 v = Getattr(p, "value"); 838 if (v) { 839 Append(t, v); 840 } else { 841 Append(t, Getattr(p, "type")); 842 } 843 } 844 Append(t, ")>"); 845 return t; 846} 847 848 849/* ----------------------------------------------------------------------------- 850 * SwigType_templateprefix() 851 * 852 * Returns the prefix before the first template definition. 853 * For example: 854 * 855 * Foo<(p.int)>::bar 856 * 857 * returns "Foo" 858 * ----------------------------------------------------------------------------- */ 859 860String *SwigType_templateprefix(const SwigType *t) { 861 const char *s = Char(t); 862 const char *c = strstr(s, "<("); 863 return c ? NewStringWithSize(s, c - s) : NewString(s); 864} 865 866/* ----------------------------------------------------------------------------- 867 * SwigType_templatesuffix() 868 * 869 * Returns text after a template substitution. Used to handle scope names 870 * for example: 871 * 872 * Foo<(p.int)>::bar 873 * 874 * returns "::bar" 875 * ----------------------------------------------------------------------------- */ 876 877String *SwigType_templatesuffix(const SwigType *t) { 878 const char *c; 879 c = Char(t); 880 while (*c) { 881 if ((*c == '<') && (*(c + 1) == '(')) { 882 int nest = 1; 883 c++; 884 while (*c && nest) { 885 if (*c == '<') 886 nest++; 887 if (*c == '>') 888 nest--; 889 c++; 890 } 891 return NewString(c); 892 } 893 c++; 894 } 895 return NewStringEmpty(); 896} 897 898/* ----------------------------------------------------------------------------- 899 * SwigType_templateargs() 900 * 901 * Returns the template arguments 902 * For example: 903 * 904 * Foo<(p.int)>::bar 905 * 906 * returns "<(p.int)>" 907 * ----------------------------------------------------------------------------- */ 908 909String *SwigType_templateargs(const SwigType *t) { 910 const char *c; 911 const char *start; 912 c = Char(t); 913 while (*c) { 914 if ((*c == '<') && (*(c + 1) == '(')) { 915 int nest = 1; 916 start = c; 917 c++; 918 while (*c && nest) { 919 if (*c == '<') 920 nest++; 921 if (*c == '>') 922 nest--; 923 c++; 924 } 925 return NewStringWithSize(start, c - start); 926 } 927 c++; 928 } 929 return 0; 930} 931 932/* ----------------------------------------------------------------------------- 933 * SwigType_istemplate() 934 * 935 * Tests a type to see if it includes template parameters 936 * ----------------------------------------------------------------------------- */ 937 938int SwigType_istemplate(const SwigType *t) { 939 char *ct = Char(t); 940 ct = strstr(ct, "<("); 941 if (ct && (strstr(ct + 2, ")>"))) 942 return 1; 943 return 0; 944} 945 946/* ----------------------------------------------------------------------------- 947 * SwigType_base() 948 * 949 * This function returns the base of a type. For example, if you have a 950 * type "p.p.int", the function would return "int". 951 * ----------------------------------------------------------------------------- */ 952 953SwigType *SwigType_base(const SwigType *t) { 954 char *c; 955 char *lastop = 0; 956 c = Char(t); 957 958 lastop = c; 959 960 /* Search for the last type constructor separator '.' */ 961 while (*c) { 962 if (*c == '.') { 963 if (*(c + 1)) { 964 lastop = c + 1; 965 } 966 c++; 967 continue; 968 } 969 if (*c == '<') { 970 /* Skip over template---it's part of the base name */ 971 int ntemp = 1; 972 c++; 973 while ((*c) && (ntemp > 0)) { 974 if (*c == '>') 975 ntemp--; 976 else if (*c == '<') 977 ntemp++; 978 c++; 979 } 980 if (ntemp) 981 break; 982 continue; 983 } 984 if (*c == '(') { 985 /* Skip over params */ 986 int nparen = 1; 987 c++; 988 while ((*c) && (nparen > 0)) { 989 if (*c == '(') 990 nparen++; 991 else if (*c == ')') 992 nparen--; 993 c++; 994 } 995 if (nparen) 996 break; 997 continue; 998 } 999 c++; 1000 } 1001 return NewString(lastop); 1002} 1003 1004/* ----------------------------------------------------------------------------- 1005 * SwigType_prefix() 1006 * 1007 * Returns the prefix of a datatype. For example, the prefix of the 1008 * type "p.p.int" is "p.p.". 1009 * ----------------------------------------------------------------------------- */ 1010 1011String *SwigType_prefix(const SwigType *t) { 1012 char *c, *d; 1013 String *r = 0; 1014 1015 c = Char(t); 1016 d = c + strlen(c); 1017 1018 /* Check for a type constructor */ 1019 if ((d > c) && (*(d - 1) == '.')) 1020 d--; 1021 1022 while (d > c) { 1023 d--; 1024 if (*d == '>') { 1025 int nest = 1; 1026 d--; 1027 while ((d > c) && (nest)) { 1028 if (*d == '>') 1029 nest++; 1030 if (*d == '<') 1031 nest--; 1032 d--; 1033 } 1034 } 1035 if (*d == ')') { 1036 /* Skip over params */ 1037 int nparen = 1; 1038 d--; 1039 while ((d > c) && (nparen)) { 1040 if (*d == ')') 1041 nparen++; 1042 if (*d == '(') 1043 nparen--; 1044 d--; 1045 } 1046 } 1047 1048 if (*d == '.') { 1049 char t = *(d + 1); 1050 *(d + 1) = 0; 1051 r = NewString(c); 1052 *(d + 1) = t; 1053 return r; 1054 } 1055 } 1056 return NewStringEmpty(); 1057} 1058 1059/* ----------------------------------------------------------------------------- 1060 * SwigType_strip_qualifiers() 1061 * 1062 * Strip all qualifiers from a type and return a new type 1063 * ----------------------------------------------------------------------------- */ 1064 1065SwigType *SwigType_strip_qualifiers(SwigType *t) { 1066 static Hash *memoize_stripped = 0; 1067 SwigType *r; 1068 List *l; 1069 Iterator ei; 1070 1071 if (!memoize_stripped) 1072 memoize_stripped = NewHash(); 1073 r = Getattr(memoize_stripped, t); 1074 if (r) 1075 return Copy(r); 1076 1077 l = SwigType_split(t); 1078 r = NewStringEmpty(); 1079 1080 for (ei = First(l); ei.item; ei = Next(ei)) { 1081 if (SwigType_isqualifier(ei.item)) 1082 continue; 1083 Append(r, ei.item); 1084 } 1085 Delete(l); 1086 { 1087 String *key, *value; 1088 key = Copy(t); 1089 value = Copy(r); 1090 Setattr(memoize_stripped, key, value); 1091 Delete(key); 1092 Delete(value); 1093 } 1094 return r; 1095} 1096