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.
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 * ----------------------------------------------------------------------------- */
13 char cvsroot_typeobj_c[] = "$Id: typeobj.c 11080 2009-01-24 13:15:51Z bhy $";
18 /* -----------------------------------------------------------------------------
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.
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...).
32 * Types are encoded as strings of type constructors such as follows:
34 * String Encoding C Example
35 * --------------- ---------
37 * a(300).a(400).int int [300][400]
38 * p.q(const).char char const *
40 * All type constructors are denoted by a trailing '.':
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::*)
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".
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:
57 * "p.p." + "a(400).int" = "p.p.a(400).int"
59 * For C++, typenames may be parameterized using <(...)>. Here are some
62 * String Encoding C++ Example
63 * --------------- ------------
64 * p.vector<(int)> vector<int> *
65 * r.foo<(int,p.double)> foo<int,double *> &
67 * Contents of this file:
69 * Most of this functions in this file pertain to the low-level manipulation
70 * of type objects. There are constructor functions like this:
72 * SwigType_add_pointer()
73 * SwigType_add_reference()
74 * SwigType_add_array()
76 * These are used to build new types. There are also functions to undo these
77 * operations. For example:
79 * SwigType_del_pointer()
80 * SwigType_del_reference()
81 * SwigType_del_array()
83 * In addition, there are query functions
85 * SwigType_ispointer()
86 * SwigType_isreference()
89 * Finally, there are some data extraction functions that can be used to
90 * extract array dimensions, template arguments, and so forth.
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:
96 * typedef int *intptr;
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
102 * ----------------------------------------------------------------------------- */
105 /* -----------------------------------------------------------------------------
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 * ----------------------------------------------------------------------------- */
113 SwigType *NewSwigType(const_String_or_char_ptr initial) {
114 return NewString(initial);
119 /* The next few functions are utility functions used in the construction and
120 management of types */
122 /* -----------------------------------------------------------------------------
123 * static element_size()
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.
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 * ----------------------------------------------------------------------------- */
133 static int element_size(char *c) {
139 return (int) (c - s);
140 } else if (*c == '(') {
157 return (int) (c - s);
160 /* -----------------------------------------------------------------------------
161 * SwigType_del_element()
163 * Deletes one type element from the type.
164 * ----------------------------------------------------------------------------- */
166 SwigType *SwigType_del_element(SwigType *t) {
167 int sz = element_size(Char(t));
172 /* -----------------------------------------------------------------------------
175 * Pop one type element off the type.
176 * ----------------------------------------------------------------------------- */
178 SwigType *SwigType_pop(SwigType *t) {
187 sz = element_size(c);
188 result = NewStringWithSize(c, sz);
197 /* -----------------------------------------------------------------------------
200 * Returns the parameter of an operator as a string
201 * ----------------------------------------------------------------------------- */
203 String *SwigType_parm(SwigType *t) {
208 while (*c && (*c != '(') && (*c != '.'))
210 if (!*c || (*c == '.'))
219 } else if (*c == '(') {
224 return NewStringWithSize(start, (int) (c - start));
227 /* -----------------------------------------------------------------------------
230 * Splits a type into it's component parts and returns a list of string.
231 * ----------------------------------------------------------------------------- */
233 List *SwigType_split(const SwigType *t) {
242 len = element_size(c);
243 item = NewStringWithSize(c, len);
253 /* -----------------------------------------------------------------------------
254 * SwigType_parmlist()
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
262 * Foo(std::string,p.f().Bar<(int,double)>)
264 * returns 2 elements in the list:
266 * p.f().Bar<(int,double)>
267 * ----------------------------------------------------------------------------- */
269 List *SwigType_parmlist(const String *p) {
278 while (*c && (*c != '(') && (*c != '.'))
282 assert(*c != '.'); /* p is expected to contain sub elements of a type */
288 size = (int) (c - itemstart);
289 item = NewStringWithSize(itemstart, size);
293 } else if (*c == '(') {
306 } else if (*c == ')') {
312 size = (int) (c - itemstart);
314 item = NewStringWithSize(itemstart, size);
321 /* -----------------------------------------------------------------------------
324 * SwigType_add_pointer()
325 * SwigType_del_pointer()
326 * SwigType_ispointer()
328 * Add, remove, and test if a type is a pointer. The deletion and query
329 * functions take into account qualifiers (if any).
330 * ----------------------------------------------------------------------------- */
332 SwigType *SwigType_add_pointer(SwigType *t) {
337 SwigType *SwigType_del_pointer(SwigType *t) {
341 /* Skip qualifiers, if any */
342 if (strncmp(c, "q(", 2) == 0) {
347 if (strncmp(c, "p.", 2)) {
348 printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
351 Delslice(t, 0, (c - s) + 2);
355 int SwigType_ispointer(SwigType *t) {
360 /* Skip qualifiers, if any */
361 if (strncmp(c, "q(", 2) == 0) {
367 if (strncmp(c, "p.", 2) == 0) {
373 /* -----------------------------------------------------------------------------
376 * SwigType_add_reference()
377 * SwigType_del_reference()
378 * SwigType_isreference()
380 * Add, remove, and test if a type is a reference. The deletion and query
381 * functions take into account qualifiers (if any).
382 * ----------------------------------------------------------------------------- */
384 SwigType *SwigType_add_reference(SwigType *t) {
389 SwigType *SwigType_del_reference(SwigType *t) {
391 int check = strncmp(c, "r.", 2);
397 int SwigType_isreference(SwigType *t) {
402 if (strncmp(c, "r.", 2) == 0) {
408 /* -----------------------------------------------------------------------------
411 * SwigType_add_qualifier()
412 * SwigType_del_qualifier()
413 * SwigType_is_qualifier()
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 * ----------------------------------------------------------------------------- */
422 SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
423 char temp[256], newq[256];
430 if (!(strncmp(c, "q(", 2) == 0)) {
431 sprintf(temp, "q(%s).", cqual);
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
441 sz = element_size(c);
442 strncpy(temp, c, (sz < 256) ? sz : 256);
444 if (strstr(temp, cqual)) {
445 /* Qualifier already added */
449 /* Add the qualifier to the existing list. */
453 q = strtok(q, " ).");
455 if (strcmp(cqual, q) < 0) {
456 /* New qualifier is less that current qualifier. We need to insert it */
464 q = strtok(NULL, " ).");
479 SwigType *SwigType_del_qualifier(SwigType *t) {
481 int check = strncmp(c, "q(", 2);
483 Delslice(t, 0, element_size(c));
487 int SwigType_isqualifier(SwigType *t) {
492 if (strncmp(c, "q(", 2) == 0) {
498 /* -----------------------------------------------------------------------------
500 * ----------------------------------------------------------------------------- */
502 int SwigType_isfunctionpointer(SwigType *t) {
507 if (strncmp(c, "p.f(", 4) == 0) {
513 /* -----------------------------------------------------------------------------
514 * SwigType_functionpointer_decompose
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 * ----------------------------------------------------------------------------- */
521 SwigType *SwigType_functionpointer_decompose(SwigType *t) {
523 assert(SwigType_isfunctionpointer(t));
530 /* -----------------------------------------------------------------------------
533 * SwigType_add_memberpointer()
534 * SwigType_del_memberpointer()
535 * SwigType_ismemberpointer()
537 * Add, remove, and test for C++ pointer to members.
538 * ----------------------------------------------------------------------------- */
540 SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
541 String *temp = NewStringf("m(%s).", name);
547 SwigType *SwigType_del_memberpointer(SwigType *t) {
549 int check = strncmp(c, "m(", 2);
551 Delslice(t, 0, element_size(c));
555 int SwigType_ismemberpointer(SwigType *t) {
560 if (strncmp(c, "m(", 2) == 0) {
566 /* -----------------------------------------------------------------------------
569 * SwigType_add_array()
570 * SwigType_del_array()
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 * ----------------------------------------------------------------------------- */
582 SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
585 strcat(temp, Char(size));
591 SwigType *SwigType_del_array(SwigType *t) {
593 int check = strncmp(c, "a(", 2);
595 Delslice(t, 0, element_size(c));
599 int SwigType_isarray(SwigType *t) {
604 if (strncmp(c, "a(", 2) == 0) {
610 * SwigType_prefix_is_simple_1D_array
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
615 int SwigType_prefix_is_simple_1D_array(SwigType *t) {
618 if (c && (strncmp(c, "a(", 2) == 0)) {
627 /* Remove all arrays */
628 SwigType *SwigType_pop_arrays(SwigType *t) {
630 assert(SwigType_isarray(t));
631 ta = NewStringEmpty();
632 while (SwigType_isarray(t)) {
633 SwigType *td = SwigType_pop(t);
640 /* Return number of array dimensions */
641 int SwigType_array_ndim(SwigType *t) {
645 while (c && (strncmp(c, "a(", 2) == 0)) {
653 /* Get nth array dimension */
654 String *SwigType_array_getdim(SwigType *t, int n) {
656 while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
662 String *dim = SwigType_parm(c);
663 if (SwigType_istemplate(dim)) {
664 String *ndim = SwigType_namestr(dim);
675 /* Replace nth array dimension */
676 void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
683 if (strncmp(c, "a(", 2))
686 while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
694 result = NewString(start);
695 Printf(result, "a(%s)", rep);
705 /* Return base type of an array */
706 SwigType *SwigType_array_type(SwigType *ty) {
709 while (SwigType_isarray(t)) {
710 Delete(SwigType_pop(t));
716 /* -----------------------------------------------------------------------------
719 * SwigType_add_function()
720 * SwigType_del_function()
721 * SwigType_isfunction()
722 * SwigType_pop_function()
724 * Add, remove, and test for function types.
725 * ----------------------------------------------------------------------------- */
727 /* Returns the function type, t, constructed from the parameters, parms */
728 SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
733 pstr = NewString("f(");
735 for (p = parms; p; p = nextSibling(p)) {
738 Append(pstr, Getattr(p, "type"));
745 SwigType *SwigType_pop_function(SwigType *t) {
749 if (strncmp(c, "q(", 2) == 0) {
753 if (strncmp(c, "f(", 2)) {
754 printf("Fatal error. SwigType_pop_function applied to non-function.\n");
764 int SwigType_isfunction(SwigType *t) {
770 if (strncmp(c, "q(", 2) == 0) {
771 /* Might be a 'const' function. Try to skip over the 'const' */
778 if (strncmp(c, "f(", 2) == 0) {
784 ParmList *SwigType_function_parms(SwigType *t) {
785 List *l = SwigType_parmlist(t);
786 Hash *p, *pp = 0, *firstp = 0;
789 for (o = First(l); o.item; o = Next(o)) {
790 p = NewParm(o.item, 0);
794 set_nextSibling(pp, p);
803 int SwigType_isvarargs(const SwigType *t) {
804 if (Strcmp(t, "v(...)") == 0)
809 /* -----------------------------------------------------------------------------
812 * SwigType_add_template()
815 * ----------------------------------------------------------------------------- */
817 /* -----------------------------------------------------------------------------
818 * SwigType_add_template()
820 * Adds a template to a type. This template is encoded in the SWIG type
821 * mechanism and produces a string like this:
823 * vector<int *> ----> "vector<(p.int)>"
824 * ----------------------------------------------------------------------------- */
826 SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
831 for (p = parms; p; p = nextSibling(p)) {
833 if (Getattr(p, "default"))
837 v = Getattr(p, "value");
841 Append(t, Getattr(p, "type"));
849 /* -----------------------------------------------------------------------------
850 * SwigType_templateprefix()
852 * Returns the prefix before the first template definition.
858 * ----------------------------------------------------------------------------- */
860 String *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);
866 /* -----------------------------------------------------------------------------
867 * SwigType_templatesuffix()
869 * Returns text after a template substitution. Used to handle scope names
875 * ----------------------------------------------------------------------------- */
877 String *SwigType_templatesuffix(const SwigType *t) {
881 if ((*c == '<') && (*(c + 1) == '(')) {
895 return NewStringEmpty();
898 /* -----------------------------------------------------------------------------
899 * SwigType_templateargs()
901 * Returns the template arguments
906 * returns "<(p.int)>"
907 * ----------------------------------------------------------------------------- */
909 String *SwigType_templateargs(const SwigType *t) {
914 if ((*c == '<') && (*(c + 1) == '(')) {
925 return NewStringWithSize(start, c - start);
932 /* -----------------------------------------------------------------------------
933 * SwigType_istemplate()
935 * Tests a type to see if it includes template parameters
936 * ----------------------------------------------------------------------------- */
938 int SwigType_istemplate(const SwigType *t) {
940 ct = strstr(ct, "<(");
941 if (ct && (strstr(ct + 2, ")>")))
946 /* -----------------------------------------------------------------------------
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 * ----------------------------------------------------------------------------- */
953 SwigType *SwigType_base(const SwigType *t) {
960 /* Search for the last type constructor separator '.' */
970 /* Skip over template---it's part of the base name */
973 while ((*c) && (ntemp > 0)) {
985 /* Skip over params */
988 while ((*c) && (nparen > 0)) {
1001 return NewString(lastop);
1004 /* -----------------------------------------------------------------------------
1007 * Returns the prefix of a datatype. For example, the prefix of the
1008 * type "p.p.int" is "p.p.".
1009 * ----------------------------------------------------------------------------- */
1011 String *SwigType_prefix(const SwigType *t) {
1018 /* Check for a type constructor */
1019 if ((d > c) && (*(d - 1) == '.'))
1027 while ((d > c) && (nest)) {
1036 /* Skip over params */
1039 while ((d > c) && (nparen)) {
1056 return NewStringEmpty();
1059 /* -----------------------------------------------------------------------------
1060 * SwigType_strip_qualifiers()
1062 * Strip all qualifiers from a type and return a new type
1063 * ----------------------------------------------------------------------------- */
1065 SwigType *SwigType_strip_qualifiers(SwigType *t) {
1066 static Hash *memoize_stripped = 0;
1071 if (!memoize_stripped)
1072 memoize_stripped = NewHash();
1073 r = Getattr(memoize_stripped, t);
1077 l = SwigType_split(t);
1078 r = NewStringEmpty();
1080 for (ei = First(l); ei.item; ei = Next(ei)) {
1081 if (SwigType_isqualifier(ei.item))
1087 String *key, *value;
1090 Setattr(memoize_stripped, key, value);