
+static CMPIType parse_int_property(const char *string, + const char *type, + CMPIValue *val) +{ + int size; + bool sign; + CMPIType t; + int ret; + + if (sscanf(type, "uint%i", &size) == 1) + sign = false; + else if (sscanf(type, "int%i", &size) == 1) + sign = true; + else { + printf("Unknown integer type: `%s'", type); + return 0;
Should this be CMPI_null? I know they're equivalent, but it might be good to use CMPI_null for clarity (and the unlikely chance that the value for CMPI_null is changed)
+ +static bool parse_array_property(const CMPIBroker *broker, + xmlNode *node, + CMPIInstance *inst) +{ + char *name = NULL; + char *tstr = NULL; + bool ret = false; + xmlNode *val_arr; + CMPIArray *array; + CMPIType type; + + name = get_attr(node, "NAME"); + if (name == NULL) { + printf("Unnamed property\n"); + goto out; + } + + tstr = get_attr(node, "TYPE"); + if (tstr == NULL) { + printf("No type\n"); + goto out; + } + + printf("Array property `%s' of type `%s'\n", name, tstr); + + for (val_arr = node->children; val_arr; val_arr = val_arr->next) { + if (val_arr->type != XML_ELEMENT_NODE) + continue; + + if (!STREQC((char *)val_arr->name, "value.array")) { + printf("Expected <value.array> but got <%s>", + val_arr->name); + goto out; + } + + break; + }
Should we use some kind of found flag here? What if val_arr->type never equals XML_ELEMENT_NODE. Then we pass the last value of val_arr to the function below, even if the element type doesn't equal XML_ELEMENT_NODE. Or do we know for sure that val_arr will have an element with XML_ELEMENT_NODE type?
+ + type = parse_array(broker, tstr, val_arr, &array); + if (type != CMPI_null) { + CU_DEBUG("Setting array property"); + CMSetProperty(inst, name, &array, (CMPI_ARRAY | type)); + } + + out: + free(name); + free(tstr); + + return ret; +} +
+ +static CMPIStatus parse_instance(const CMPIBroker *broker, + const char *ns, + xmlNode *root, + CMPIInstance **inst) +{ + char *class = NULL; + xmlNode *child; + CMPIStatus s; + CMPIObjectPath *op; + + if (root->type != XML_ELEMENT_NODE) { + printf("First node is not <INSTANCE>\n"); + goto out; + } + + if (!STREQC((char *)root->name, "instance")) { + printf("Got node %s, expecting INSTANCE\n", root->name); + goto out; + } + + class = get_attr(root, "CLASSNAME"); + if (class == NULL) { + printf("No Classname\n"); + goto out; + }
For these statements above, should we set s.rc to some kind of error return code? Otherwise, we are returning a non-initialized status. Currently, this isn't a problem since the return value of parse_instance() isn't caught (see cu_parse_ei_xml() below)... so this might not need to be changed.
+ + CU_DEBUG("Instance of %s", class); + + op = CMNewObjectPath(broker, ns, class, &s); + if ((op == NULL) || (s.rc != CMPI_RC_OK)) { + CU_DEBUG("Unable to create path for %s:%s", ns, class); + goto out; + } + + *inst = CMNewInstance(broker, op, &s); + if ((*inst == NULL) || (s.rc != CMPI_RC_OK)) { + CU_DEBUG("Unable to create inst for %s:%s", ns, class); + goto out; + } + + for (child = root->children; child; child = child->next) { + if (child->type == XML_ELEMENT_NODE){ + if (STREQC((char *)child->name, "property")) + parse_property(broker, child, *inst); + else if (STREQC((char *)child->name, "property.array")) + parse_array_property(broker, child, *inst); + else + printf("Unexpected node: %s\n", child->name); + } + } + + out: + free(class); + + return s; +} + +#if 0 + +/* This isn't currently used but I think I might need it for nested + * instances, depending on how they look. + */ + +static char *parse_esc(const char *start, char *result) +{ + char *delim; + char *escape = NULL; + int len = 1; + + delim = strchr(start, ';'); + if (delim == NULL) + goto out; + + escape = strndup(start, delim - start + 1); + if (escape == NULL) { + CU_DEBUG("Memory alloc failed (%i)", delim-start); + return NULL; + } + + CU_DEBUG("Escape is: %s", escape); + + if (STREQC(escape, "<")) + *result = '<'; + else if (STREQC(escape, ">")) + *result = '>'; + else if (STREQC(escape, """)) + *result = '\"'; + else + CU_DEBUG("Unhandled escape: `%s'", escape);
Would it be worthwhile to return NULL here? We return a pointer to a string, but the string might not be a valid element name because the escape isn't supported. Or should the caller check the result to make sure it's valid before continuing on?
+ + len = strlen(escape); + + out: + free(escape); + + return (char *)start + len; +} + +static char *xml_decode(const char *input) +{ + const char *iptr = input; + char *optr; + char *res = NULL; + + res = malloc(strlen(input) + 1); + if (res == NULL) + return res; + + optr = res; + + while (iptr && (*iptr != '\0')) {
Just a style note, but for non-boolean variables, aren't we trying to use something like: (iptr != NULL)?
+ if (*iptr == '&') { + iptr = parse_esc(iptr, optr); + } else { + *optr = *iptr; + iptr++; + } + + optr++; + } + + return res; +} + +#endif + +int cu_parse_ei_xml(const CMPIBroker *broker, + const char *ns, + const char *xml, + CMPIInstance **instance) +{ + xmlDoc *doc = NULL; + xmlNode *root = NULL; + int ret = 0; + + doc = xmlReadMemory(xml, strlen(xml), NULL, NULL, 0); + if (doc == NULL) { + CU_DEBUG("Error reading decoded XML from memory"); + goto out; ret isn't updated to indicate an error here. + } + + root = xmlDocGetRootElement(doc); + if (root == NULL) { + CU_DEBUG("Error getting root XML node"); + goto out; + } + + parse_instance(broker, ns, root, instance);
The return status isn't caught here. parse_instance() could return something other than CMPI_RC_OK if CMNewObjectPath() or CMNewInstance() fail.
+ + out: + xmlFreeDoc(doc); + + return ret; +} +
I know this just and RFC, but don't forget to remove printfs or convert them to CU_DEBUGs. =) -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com