/* * Create a new type hint for a raw string. */ typeHintDef *newTypeHint(char *raw_hint) { typeHintDef *thd = sipMalloc(sizeof (typeHintDef)); thd->status = needs_parsing; thd->raw_hint = raw_hint; return thd; }
/* * Copy the root node of a type hint. */ static typeHintNodeDef *copyTypeHintNode(sipSpec *pt, typeHintDef *thd, int out) { typeHintNodeDef *node; parseTypeHint(pt, thd, out); if (thd->root == NULL) return NULL; node = sipMalloc(sizeof (typeHintNodeDef)); *node = *thd->root; node->next = NULL; return node; }
/* * Append a string to a list of them. */ void appendString(stringList **headp, const char *s) { stringList *sl; /* Create the new entry. */ sl = sipMalloc(sizeof (stringList)); sl -> s = s; sl -> next = NULL; /* Append it to the list. */ while (*headp != NULL) headp = &(*headp) -> next; *headp = sl; }
/* * Look up a qualified Python type and return the corresponding node (or NULL * if the type should be omitted because of a recursive definition). */ static typeHintNodeDef *lookupType(sipSpec *pt, char *name, int out) { char *sp, *ep; classDef *scope_cd; mappedTypeDef *scope_mtd; typeHintDef *thd; typeHintNodeDef *node; /* Start searching at the global level. */ scope_cd = NULL; scope_mtd = NULL; sp = name; ep = NULL; while (*sp != '\0') { enumDef *ed; /* Isolate the next part of the name. */ if ((ep = strchr(sp, '.')) != NULL) *ep = '\0'; /* See if it's an enum. */ if ((ed = lookupEnum(pt, sp, scope_cd, scope_mtd)) != NULL) { /* Make sure we have used the whole name. */ if (ep == NULL) { node = sipMalloc(sizeof (typeHintNodeDef)); node->type = enum_node; node->u.ed = ed; return node; } /* There is some left so the whole lookup has failed. */ break; } /* * If we have a mapped type scope then we must be looking for an enum, * which we have failed to find. */ if (scope_mtd != NULL) break; if (scope_cd == NULL) { mappedTypeDef *mtd; /* * We are looking at the global level, so see if it is a mapped * type. */ if ((mtd = lookupMappedType(pt, sp)) != NULL) { /* * If we have used the whole name then the lookup has * succeeded. */ if (ep == NULL) { thd = (out ? mtd->typehint_out : mtd->typehint_in); if (thd != NULL && thd->status != being_parsed) return copyTypeHintNode(pt, thd, out); /* * If we get here we have a recursively defined mapped type * so we simply omit it. */ return NULL; } /* Otherwise this is the scope for the next part. */ scope_mtd = mtd; } } if (scope_mtd == NULL) { classDef *cd; /* If we get here then it must be a class. */ if ((cd = lookupClass(pt, sp, scope_cd)) == NULL) break; /* If we have used the whole name then the lookup has succeeded. */ if (ep == NULL) { thd = (out ? cd->typehint_out : cd->typehint_in); if (thd != NULL && thd->status != being_parsed) return copyTypeHintNode(pt, thd, out); node = sipMalloc(sizeof (typeHintNodeDef)); node->type = class_node; node->u.cd = cd; return node; } /* Otherwise this is the scope for the next part. */ scope_cd = cd; } /* If we have run out of name then the lookup has failed. */ if (ep == NULL) break; /* Repair the name and go on to the next part. */ *ep++ = '.'; sp = ep; } /* Repair the name. */ if (ep != NULL) *ep = '.'; /* Nothing was found. */ node = sipMalloc(sizeof (typeHintNodeDef)); node->type = other_node; node->u.name = sipStrdup(name); return node; }
/* * Recursively parse a type hint. Return FALSE if the parse failed. */ static int parseTypeHintNode(sipSpec *pt, int out, int top_level, char *start, char *end, typeHintNodeDef **thnp) { char *cp, *name_start, *name_end; int have_brackets = FALSE; typeHintNodeDef *node, *children = NULL; /* Assume there won't be a node. */ *thnp = NULL; /* Find the name and any opening and closing bracket. */ strip_leading(&start, end); name_start = start; strip_trailing(start, &end); name_end = end; for (cp = start; cp < end; ++cp) if (*cp == '[') { typeHintNodeDef **tail = &children; /* The last character must be a closing bracket. */ if (end[-1] != ']') return FALSE; /* Find the end of any name. */ name_end = cp; strip_trailing(name_start, &name_end); for (;;) { char *pp; int depth; /* Skip the opening bracket or comma. */ ++cp; /* Find the next comma, if any. */ depth = 0; for (pp = cp; pp < end; ++pp) if (*pp == '[') { ++depth; } else if (*pp == ']' && depth != 0) { --depth; } else if ((*pp == ',' || *pp == ']') && depth == 0) { typeHintNodeDef *child; /* Recursively parse this part. */ if (!parseTypeHintNode(pt, out, FALSE, cp, pp, &child)) return FALSE; if (child != NULL) { /* * Append the child to the list of children. There * might not be a child if we have detected a * recursive definition. */ *tail = child; tail = &child->next; } cp = pp; break; } if (pp == end) break; } have_brackets = TRUE; break; } /* We must have a name unless we have empty brackets. */ if (name_start == name_end) { if (top_level && have_brackets && children == NULL) return FALSE; /* Return the representation of empty brackets. */ node = sipMalloc(sizeof (typeHintNodeDef)); node->type = brackets_node; } else { char saved; const char *typing; /* Isolate the name. */ saved = *name_end; *name_end = '\0'; /* See if it is an object in the typing module. */ if ((typing = typingModule(name_start)) != NULL) { if (strcmp(typing, "Union") == 0) { /* * If there are no children assume it is because they have been * omitted. */ if (children == NULL) return TRUE; children = flatten_unions(children); } node = sipMalloc(sizeof (typeHintNodeDef)); node->type = typing_node; node->u.name = typing; node->children = children; } else { /* Search for the type. */ node = lookupType(pt, name_start, out); } *name_end = saved; /* Only objects from the typing module can have brackets. */ if (typing == NULL && have_brackets) return FALSE; } *thnp = node; return TRUE; }
// Convert the Python values to a raw array. static void *convert_values(Array *array, PyObject *values, GLenum gl_type, sipErrorState *estate) { #if PY_VERSION_HEX >= 0x02060300 int rc = sipGetBufferInfo(values, &array->buffer); if (rc < 0) { *estate = sipErrorFail; return 0; } if (rc > 0) { // Check the buffer is compatible with what we need. GLenum array_type; switch (*array->buffer.bi_format) { case 'b': array_type = GL_BYTE; break; case 'B': array_type = GL_UNSIGNED_BYTE; break; case 'h': array_type = GL_SHORT; break; case 'H': array_type = GL_UNSIGNED_SHORT; break; case 'i': array_type = GL_INT; break; case 'I': array_type = GL_UNSIGNED_INT; break; case 'f': array_type = GL_FLOAT; break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) case 'd': array_type = GL_DOUBLE; break; #endif default: PyErr_Format(PyExc_TypeError, "unsupported buffer type '%s'", array->buffer.bi_format); *estate = sipErrorFail; return 0; } if (array_type != gl_type) { PyErr_SetString(PyExc_TypeError, "the buffer type is not the same as the array type"); *estate = sipErrorFail; return 0; } return array->buffer.bi_buf; } #else PyBufferProcs *bf = Py_TYPE(values)->tp_as_buffer; if (bf && bf->bf_getreadbuffer && bf->bf_getsegcount) { if (bf->bf_getsegcount(values, 0) != 1) { PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected"); *estate = sipErrorFail; return 0; } if (bf->bf_getreadbuffer(values, 0, reinterpret_cast<void **>(&array)) < 0) { *estate = sipErrorFail; return 0; } Py_INCREF(values); array->buffer = values; return array; } #endif PyObject *seq = PySequence_Fast(values, "array must be a sequence or a buffer"); if (!seq) { *estate = sipErrorContinue; return 0; } Py_ssize_t nr_items = Sequence_Fast_Size(seq); if (nr_items < 1) { Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "array must have at least one element"); *estate = sipErrorFail; return 0; } void (*convertor)(PyObject *, void *, Py_ssize_t); size_t element_size; switch (gl_type) { case GL_BYTE: convertor = convert_byte; element_size = sizeof (GLbyte); break; case GL_UNSIGNED_BYTE: convertor = convert_ubyte; element_size = sizeof (GLubyte); break; case GL_SHORT: convertor = convert_short; element_size = sizeof (GLshort); break; case GL_UNSIGNED_SHORT: convertor = convert_ushort; element_size = sizeof (GLushort); break; case GL_INT: convertor = convert_int; element_size = sizeof (GLint); break; case GL_UNSIGNED_INT: convertor = convert_uint; element_size = sizeof (GLuint); break; case GL_FLOAT: convertor = convert_float; element_size = sizeof (GLfloat); break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) #if GL_DOUBLE != GL_FLOAT case GL_DOUBLE: convertor = convert_double; element_size = sizeof (GLdouble); break; #endif #endif default: Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "unsupported GL element type"); *estate = sipErrorFail; return 0; } void *data = sipMalloc(nr_items * element_size); if (!data) { Py_DECREF(seq); *estate = sipErrorFail; return 0; } for (Py_ssize_t i = 0; i < nr_items; ++i) { PyErr_Clear(); convertor(Sequence_Fast_GetItem(seq, i), data, i); if (PyErr_Occurred()) { sipFree(data); Py_DECREF(seq); *estate = sipErrorFail; return 0; } } Py_DECREF(seq); array->data = data; return data; }