+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(a)linux.vnet.ibm.com