summaryrefslogtreecommitdiff
path: root/Source/Swig/typeobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Swig/typeobj.c')
-rw-r--r--Source/Swig/typeobj.c1095
1 files changed, 1095 insertions, 0 deletions
diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c
new file mode 100644
index 0000000..085fda3
--- /dev/null
+++ b/Source/Swig/typeobj.c
@@ -0,0 +1,1095 @@
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * typeobj.c
+ *
+ * This file provides functions for constructing, manipulating, and testing
+ * type objects. Type objects are merely the raw low-level representation
+ * of C++ types. They do not incorporate high-level type system features
+ * like typedef, namespaces, etc.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_typeobj_c[] = "$Id: typeobj.c 11080 2009-01-24 13:15:51Z bhy $";
+
+#include "swig.h"
+#include <ctype.h>
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This file provides a collection of low-level functions for constructing and
+ * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple
+ * text strings. This representation is compact, easy to debug, and easy to read.
+ *
+ * General idea:
+ *
+ * Types are represented by a base type (e.g., "int") and a collection of
+ * type operators applied to the base (e.g., pointers, arrays, etc...).
+ *
+ * Encoding:
+ *
+ * Types are encoded as strings of type constructors such as follows:
+ *
+ * String Encoding C Example
+ * --------------- ---------
+ * p.p.int int **
+ * a(300).a(400).int int [300][400]
+ * p.q(const).char char const *
+ *
+ * All type constructors are denoted by a trailing '.':
+ *
+ * 'p.' = Pointer (*)
+ * 'r.' = Reference (&)
+ * 'a(n).' = Array of size n [n]
+ * 'f(..,..).' = Function with arguments (args)
+ * 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
+ * 'm(qual).' = Pointer to member (qual::*)
+ *
+ * The encoding follows the order that you might describe a type in words.
+ * For example "p.a(200).int" is "A pointer to array of int's" and
+ * "p.q(const).char" is "a pointer to a const char".
+ *
+ * This representation of types is fairly convenient because ordinary string
+ * operations can be used for type manipulation. For example, a type could be
+ * formed by combining two strings such as the following:
+ *
+ * "p.p." + "a(400).int" = "p.p.a(400).int"
+ *
+ * For C++, typenames may be parameterized using <(...)>. Here are some
+ * examples:
+ *
+ * String Encoding C++ Example
+ * --------------- ------------
+ * p.vector<(int)> vector<int> *
+ * r.foo<(int,p.double)> foo<int,double *> &
+ *
+ * Contents of this file:
+ *
+ * Most of this functions in this file pertain to the low-level manipulation
+ * of type objects. There are constructor functions like this:
+ *
+ * SwigType_add_pointer()
+ * SwigType_add_reference()
+ * SwigType_add_array()
+ *
+ * These are used to build new types. There are also functions to undo these
+ * operations. For example:
+ *
+ * SwigType_del_pointer()
+ * SwigType_del_reference()
+ * SwigType_del_array()
+ *
+ * In addition, there are query functions
+ *
+ * SwigType_ispointer()
+ * SwigType_isreference()
+ * SwigType_isarray()
+ *
+ * Finally, there are some data extraction functions that can be used to
+ * extract array dimensions, template arguments, and so forth.
+ *
+ * It is very important for developers to realize that the functions in this
+ * module do *NOT* incorporate higher-level type system features like typedef.
+ * For example, you could have C code like this:
+ *
+ * typedef int *intptr;
+ *
+ * In this case, a SwigType of type 'intptr' will be treated as a simple type and
+ * functions like SwigType_ispointer() will evaluate as false. It is strongly
+ * advised that developers use the TypeSys_* interface to check types in a more
+ * reliable manner.
+ * ----------------------------------------------------------------------------- */
+
+
+/* -----------------------------------------------------------------------------
+ * NewSwigType()
+ *
+ * Constructs a new type object. Eventually, it would be nice for this function
+ * to accept an initial value in the form a C/C++ abstract type (currently unimplemented).
+ * ----------------------------------------------------------------------------- */
+
+#ifdef NEW
+SwigType *NewSwigType(const_String_or_char_ptr initial) {
+ return NewString(initial);
+}
+
+#endif
+
+/* The next few functions are utility functions used in the construction and
+ management of types */
+
+/* -----------------------------------------------------------------------------
+ * static element_size()
+ *
+ * This utility function finds the size of a single type element in a type string.
+ * Type elements are always delimited by periods, but may be nested with
+ * parentheses. A nested element is always handled as a single item.
+ *
+ * Returns the integer size of the element (which can be used to extract a
+ * substring, to chop the element off, or for other purposes).
+ * ----------------------------------------------------------------------------- */
+
+static int element_size(char *c) {
+ int nparen;
+ char *s = c;
+ while (*c) {
+ if (*c == '.') {
+ c++;
+ return (int) (c - s);
+ } else if (*c == '(') {
+ nparen = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparen++;
+ if (*c == ')') {
+ nparen--;
+ if (nparen == 0)
+ break;
+ }
+ c++;
+ }
+ }
+ if (*c)
+ c++;
+ }
+ return (int) (c - s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_del_element()
+ *
+ * Deletes one type element from the type.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_del_element(SwigType *t) {
+ int sz = element_size(Char(t));
+ Delslice(t, 0, sz);
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop()
+ *
+ * Pop one type element off the type.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop(SwigType *t) {
+ SwigType *result;
+ char *c;
+ int sz;
+
+ c = Char(t);
+ if (!*c)
+ return 0;
+
+ sz = element_size(c);
+ result = NewStringWithSize(c, sz);
+ Delslice(t, 0, sz);
+ c = Char(t);
+ if (*c == '.') {
+ Delitem(t, 0);
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parm()
+ *
+ * Returns the parameter of an operator as a string
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_parm(SwigType *t) {
+ char *start, *c;
+ int nparens = 0;
+
+ c = Char(t);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c || (*c == '.'))
+ return 0;
+ c++;
+ start = c;
+ while (*c) {
+ if (*c == ')') {
+ if (nparens == 0)
+ break;
+ nparens--;
+ } else if (*c == '(') {
+ nparens++;
+ }
+ c++;
+ }
+ return NewStringWithSize(start, (int) (c - start));
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_split()
+ *
+ * Splits a type into it's component parts and returns a list of string.
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_split(const SwigType *t) {
+ String *item;
+ List *list;
+ char *c;
+ int len;
+
+ c = Char(t);
+ list = NewList();
+ while (*c) {
+ len = element_size(c);
+ item = NewStringWithSize(c, len);
+ Append(list, item);
+ Delete(item);
+ c = c + len;
+ if (*c == '.')
+ c++;
+ }
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parmlist()
+ *
+ * Splits a comma separated list of parameters into its component parts
+ * The input is expected to contain the parameter list within () brackets
+ * Returns 0 if no argument list in the input, ie there are no round brackets ()
+ * Returns an empty List if there are no parameters in the () brackets
+ * For example:
+ *
+ * Foo(std::string,p.f().Bar<(int,double)>)
+ *
+ * returns 2 elements in the list:
+ * std::string
+ * p.f().Bar<(int,double)>
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_parmlist(const String *p) {
+ String *item = 0;
+ List *list;
+ char *c;
+ char *itemstart;
+ int size;
+
+ assert(p);
+ c = Char(p);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c)
+ return 0;
+ assert(*c != '.'); /* p is expected to contain sub elements of a type */
+ c++;
+ list = NewList();
+ itemstart = c;
+ while (*c) {
+ if (*c == ',') {
+ size = (int) (c - itemstart);
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ Delete(item);
+ itemstart = c + 1;
+ } else if (*c == '(') {
+ int nparens = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparens++;
+ if (*c == ')') {
+ nparens--;
+ if (nparens == 0)
+ break;
+ }
+ c++;
+ }
+ } else if (*c == ')') {
+ break;
+ }
+ if (*c)
+ c++;
+ }
+ size = (int) (c - itemstart);
+ if (size > 0) {
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ }
+ Delete(item);
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pointers
+ *
+ * SwigType_add_pointer()
+ * SwigType_del_pointer()
+ * SwigType_ispointer()
+ *
+ * Add, remove, and test if a type is a pointer. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_pointer(SwigType *t) {
+ Insert(t, 0, "p.");
+ return t;
+}
+
+SwigType *SwigType_del_pointer(SwigType *t) {
+ char *c, *s;
+ c = Char(t);
+ s = c;
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ assert(c);
+ c++;
+ }
+ if (strncmp(c, "p.", 2)) {
+ printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
+ abort();
+ }
+ Delslice(t, 0, (c - s) + 2);
+ return t;
+}
+
+int SwigType_ispointer(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ if (!c)
+ return 0;
+ c++;
+ }
+ if (strncmp(c, "p.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * References
+ *
+ * SwigType_add_reference()
+ * SwigType_del_reference()
+ * SwigType_isreference()
+ *
+ * Add, remove, and test if a type is a reference. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_reference(SwigType *t) {
+ Insert(t, 0, "r.");
+ return t;
+}
+
+SwigType *SwigType_del_reference(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "r.", 2);
+ assert(check == 0);
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isreference(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "r.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Qualifiers
+ *
+ * SwigType_add_qualifier()
+ * SwigType_del_qualifier()
+ * SwigType_is_qualifier()
+ *
+ * Adds type qualifiers like "const" and "volatile". When multiple qualifiers
+ * are added to a type, they are combined together into a single qualifier.
+ * Repeated qualifications have no effect. Moreover, the order of qualifications
+ * is alphabetical---meaning that "const volatile" and "volatile const" are
+ * stored in exactly the same way as "q(const volatile)".
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
+ char temp[256], newq[256];
+ int sz, added = 0;
+ char *q, *cqual;
+
+ char *c = Char(t);
+ cqual = Char(qual);
+
+ if (!(strncmp(c, "q(", 2) == 0)) {
+ sprintf(temp, "q(%s).", cqual);
+ Insert(t, 0, temp);
+ return t;
+ }
+
+ /* The type already has a qualifier on it. In this case, we first check to
+ see if the qualifier is already specified. In that case do nothing.
+ If it is a new qualifier, we add it to the qualifier list in alphabetical
+ order */
+
+ sz = element_size(c);
+ strncpy(temp, c, (sz < 256) ? sz : 256);
+
+ if (strstr(temp, cqual)) {
+ /* Qualifier already added */
+ return t;
+ }
+
+ /* Add the qualifier to the existing list. */
+
+ strcpy(newq, "q(");
+ q = temp + 2;
+ q = strtok(q, " ).");
+ while (q) {
+ if (strcmp(cqual, q) < 0) {
+ /* New qualifier is less that current qualifier. We need to insert it */
+ strcat(newq, cqual);
+ strcat(newq, " ");
+ strcat(newq, q);
+ added = 1;
+ } else {
+ strcat(newq, q);
+ }
+ q = strtok(NULL, " ).");
+ if (q) {
+ strcat(newq, " ");
+ }
+ }
+ if (!added) {
+ strcat(newq, " ");
+ strcat(newq, cqual);
+ }
+ strcat(newq, ").");
+ Delslice(t, 0, sz);
+ Insert(t, 0, newq);
+ return t;
+}
+
+SwigType *SwigType_del_qualifier(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "q(", 2);
+ assert(check == 0);
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isqualifier(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Function Pointers
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_isfunctionpointer(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "p.f(", 4) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_functionpointer_decompose
+ *
+ * Decompose the function pointer into the parameter list and the return type
+ * t - input and on completion contains the return type
+ * returns the function's parameters
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_functionpointer_decompose(SwigType *t) {
+ String *p;
+ assert(SwigType_isfunctionpointer(t));
+ p = SwigType_pop(t);
+ Delete(p);
+ p = SwigType_pop(t);
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * Member Pointers
+ *
+ * SwigType_add_memberpointer()
+ * SwigType_del_memberpointer()
+ * SwigType_ismemberpointer()
+ *
+ * Add, remove, and test for C++ pointer to members.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
+ String *temp = NewStringf("m(%s).", name);
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+}
+
+SwigType *SwigType_del_memberpointer(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "m(", 2);
+ assert(check == 0);
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_ismemberpointer(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "m(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Arrays
+ *
+ * SwigType_add_array()
+ * SwigType_del_array()
+ * SwigType_isarray()
+ *
+ * Utility functions:
+ *
+ * SwigType_array_ndim() - Calculate number of array dimensions.
+ * SwigType_array_getdim() - Get array dimension
+ * SwigType_array_setdim() - Set array dimension
+ * SwigType_array_type() - Return array type
+ * SwigType_pop_arrays() - Remove all arrays
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
+ char temp[512];
+ strcpy(temp, "a(");
+ strcat(temp, Char(size));
+ strcat(temp, ").");
+ Insert(t, 0, temp);
+ return t;
+}
+
+SwigType *SwigType_del_array(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "a(", 2);
+ assert(check == 0);
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isarray(SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "a(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+/*
+ * SwigType_prefix_is_simple_1D_array
+ *
+ * Determine if the type is a 1D array type that is treated as a pointer within SWIG
+ * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
+ */
+int SwigType_prefix_is_simple_1D_array(SwigType *t) {
+ char *c = Char(t);
+
+ if (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ c++;
+ return (*c == 0);
+ }
+ return 0;
+}
+
+
+/* Remove all arrays */
+SwigType *SwigType_pop_arrays(SwigType *t) {
+ String *ta;
+ assert(SwigType_isarray(t));
+ ta = NewStringEmpty();
+ while (SwigType_isarray(t)) {
+ SwigType *td = SwigType_pop(t);
+ Append(ta, td);
+ Delete(td);
+ }
+ return ta;
+}
+
+/* Return number of array dimensions */
+int SwigType_array_ndim(SwigType *t) {
+ int ndim = 0;
+ char *c = Char(t);
+
+ while (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ c++;
+ ndim++;
+ }
+ return ndim;
+}
+
+/* Get nth array dimension */
+String *SwigType_array_getdim(SwigType *t, int n) {
+ char *c = Char(t);
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ c++;
+ n--;
+ }
+ if (n == 0) {
+ String *dim = SwigType_parm(c);
+ if (SwigType_istemplate(dim)) {
+ String *ndim = SwigType_namestr(dim);
+ Delete(dim);
+ dim = ndim;
+ }
+
+ return dim;
+ }
+
+ return 0;
+}
+
+/* Replace nth array dimension */
+void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
+ String *result = 0;
+ char temp;
+ char *start;
+ char *c = Char(t);
+
+ start = c;
+ if (strncmp(c, "a(", 2))
+ abort();
+
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ c++;
+ n--;
+ }
+ if (n == 0) {
+ temp = *c;
+ *c = 0;
+ result = NewString(start);
+ Printf(result, "a(%s)", rep);
+ *c = temp;
+ c = strchr(c, '.');
+ Append(result, c);
+ }
+ Clear(t);
+ Append(t, result);
+ Delete(result);
+}
+
+/* Return base type of an array */
+SwigType *SwigType_array_type(SwigType *ty) {
+ SwigType *t;
+ t = Copy(ty);
+ while (SwigType_isarray(t)) {
+ Delete(SwigType_pop(t));
+ }
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Functions
+ *
+ * SwigType_add_function()
+ * SwigType_del_function()
+ * SwigType_isfunction()
+ * SwigType_pop_function()
+ *
+ * Add, remove, and test for function types.
+ * ----------------------------------------------------------------------------- */
+
+/* Returns the function type, t, constructed from the parameters, parms */
+SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
+ String *pstr;
+ Parm *p;
+
+ Insert(t, 0, ").");
+ pstr = NewString("f(");
+ p = parms;
+ for (p = parms; p; p = nextSibling(p)) {
+ if (p != parms)
+ Putc(',', pstr);
+ Append(pstr, Getattr(p, "type"));
+ }
+ Insert(t, 0, pstr);
+ Delete(pstr);
+ return t;
+}
+
+SwigType *SwigType_pop_function(SwigType *t) {
+ SwigType *f = 0;
+ SwigType *g = 0;
+ char *c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ f = SwigType_pop(t);
+ c = Char(t);
+ }
+ if (strncmp(c, "f(", 2)) {
+ printf("Fatal error. SwigType_pop_function applied to non-function.\n");
+ abort();
+ }
+ g = SwigType_pop(t);
+ if (f)
+ SwigType_push(g, f);
+ Delete(f);
+ return g;
+}
+
+int SwigType_isfunction(SwigType *t) {
+ char *c;
+ if (!t) {
+ return 0;
+ }
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Might be a 'const' function. Try to skip over the 'const' */
+ c = strchr(c, '.');
+ if (c)
+ c++;
+ else
+ return 0;
+ }
+ if (strncmp(c, "f(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+ParmList *SwigType_function_parms(SwigType *t) {
+ List *l = SwigType_parmlist(t);
+ Hash *p, *pp = 0, *firstp = 0;
+ Iterator o;
+
+ for (o = First(l); o.item; o = Next(o)) {
+ p = NewParm(o.item, 0);
+ if (!firstp)
+ firstp = p;
+ if (pp) {
+ set_nextSibling(pp, p);
+ Delete(p);
+ }
+ pp = p;
+ }
+ Delete(l);
+ return firstp;
+}
+
+int SwigType_isvarargs(const SwigType *t) {
+ if (Strcmp(t, "v(...)") == 0)
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Templates
+ *
+ * SwigType_add_template()
+ *
+ * Template handling.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_add_template()
+ *
+ * Adds a template to a type. This template is encoded in the SWIG type
+ * mechanism and produces a string like this:
+ *
+ * vector<int *> ----> "vector<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
+ Parm *p;
+
+ Append(t, "<(");
+ p = parms;
+ for (p = parms; p; p = nextSibling(p)) {
+ String *v;
+ if (Getattr(p, "default"))
+ continue;
+ if (p != parms)
+ Append(t, ",");
+ v = Getattr(p, "value");
+ if (v) {
+ Append(t, v);
+ } else {
+ Append(t, Getattr(p, "type"));
+ }
+ }
+ Append(t, ")>");
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateprefix()
+ *
+ * Returns the prefix before the first template definition.
+ * For example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "Foo"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateprefix(const SwigType *t) {
+ const char *s = Char(t);
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, c - s) : NewString(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templatesuffix()
+ *
+ * Returns text after a template substitution. Used to handle scope names
+ * for example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "::bar"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templatesuffix(const SwigType *t) {
+ const char *c;
+ c = Char(t);
+ while (*c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ return NewString(c);
+ }
+ c++;
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateargs()
+ *
+ * Returns the template arguments
+ * For example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateargs(const SwigType *t) {
+ const char *c;
+ const char *start;
+ c = Char(t);
+ while (*c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ start = c;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ return NewStringWithSize(start, c - start);
+ }
+ c++;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate()
+ *
+ * Tests a type to see if it includes template parameters
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_istemplate(const SwigType *t) {
+ char *ct = Char(t);
+ ct = strstr(ct, "<(");
+ if (ct && (strstr(ct + 2, ")>")))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_base()
+ *
+ * This function returns the base of a type. For example, if you have a
+ * type "p.p.int", the function would return "int".
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_base(const SwigType *t) {
+ char *c;
+ char *lastop = 0;
+ c = Char(t);
+
+ lastop = c;
+
+ /* Search for the last type constructor separator '.' */
+ while (*c) {
+ if (*c == '.') {
+ if (*(c + 1)) {
+ lastop = c + 1;
+ }
+ c++;
+ continue;
+ }
+ if (*c == '<') {
+ /* Skip over template---it's part of the base name */
+ int ntemp = 1;
+ c++;
+ while ((*c) && (ntemp > 0)) {
+ if (*c == '>')
+ ntemp--;
+ else if (*c == '<')
+ ntemp++;
+ c++;
+ }
+ if (ntemp)
+ break;
+ continue;
+ }
+ if (*c == '(') {
+ /* Skip over params */
+ int nparen = 1;
+ c++;
+ while ((*c) && (nparen > 0)) {
+ if (*c == '(')
+ nparen++;
+ else if (*c == ')')
+ nparen--;
+ c++;
+ }
+ if (nparen)
+ break;
+ continue;
+ }
+ c++;
+ }
+ return NewString(lastop);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_prefix()
+ *
+ * Returns the prefix of a datatype. For example, the prefix of the
+ * type "p.p.int" is "p.p.".
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_prefix(const SwigType *t) {
+ char *c, *d;
+ String *r = 0;
+
+ c = Char(t);
+ d = c + strlen(c);
+
+ /* Check for a type constructor */
+ if ((d > c) && (*(d - 1) == '.'))
+ d--;
+
+ while (d > c) {
+ d--;
+ if (*d == '>') {
+ int nest = 1;
+ d--;
+ while ((d > c) && (nest)) {
+ if (*d == '>')
+ nest++;
+ if (*d == '<')
+ nest--;
+ d--;
+ }
+ }
+ if (*d == ')') {
+ /* Skip over params */
+ int nparen = 1;
+ d--;
+ while ((d > c) && (nparen)) {
+ if (*d == ')')
+ nparen++;
+ if (*d == '(')
+ nparen--;
+ d--;
+ }
+ }
+
+ if (*d == '.') {
+ char t = *(d + 1);
+ *(d + 1) = 0;
+ r = NewString(c);
+ *(d + 1) = t;
+ return r;
+ }
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_strip_qualifiers()
+ *
+ * Strip all qualifiers from a type and return a new type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_strip_qualifiers(SwigType *t) {
+ static Hash *memoize_stripped = 0;
+ SwigType *r;
+ List *l;
+ Iterator ei;
+
+ if (!memoize_stripped)
+ memoize_stripped = NewHash();
+ r = Getattr(memoize_stripped, t);
+ if (r)
+ return Copy(r);
+
+ l = SwigType_split(t);
+ r = NewStringEmpty();
+
+ for (ei = First(l); ei.item; ei = Next(ei)) {
+ if (SwigType_isqualifier(ei.item))
+ continue;
+ Append(r, ei.item);
+ }
+ Delete(l);
+ {
+ String *key, *value;
+ key = Copy(t);
+ value = Copy(r);
+ Setattr(memoize_stripped, key, value);
+ Delete(key);
+ Delete(value);
+ }
+ return r;
+}