📄 xen_common.c
字号:
xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; xmlNode *node0, *node1; xmlChar *status_code; if (doc == NULL) { server_error(session, "Couldn't parse the server response"); return; } xpathCtx = xmlXPathNewContext(doc); if (xpathCtx == NULL) { xmlFreeDoc(doc); server_error(session, "Couldn't create XPath context"); return; } xpathObj = xmlXPathCompiledEval(responsePath, xpathCtx); if (xpathObj == NULL) { parse_fault(session, xpathCtx); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return; } if (xpathObj->type != XPATH_NODESET || xpathObj->nodesetval->nodeNr != 2) { parse_fault(session, xpathCtx); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return; } node0 = xpathObj->nodesetval->nodeTab[0]; node1 = xpathObj->nodesetval->nodeTab[1]; status_code = string_from_value(node0, "string"); if (status_code == NULL) { xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); server_error(session, "Server response does not have a Status"); return; } if (strcmp((char *)status_code, "Success")) { parse_failure(session, node1); xmlFree(status_code); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return; } parse_into(session, node1, result_type, value, 0); xmlFree(status_code); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc);}static voidmake_body_add_type(enum abstract_typename typename, abstract_value *v, xmlNode *params_node){ char buf[20]; switch (typename) { case STRING: add_param(params_node, "string", v->u.string_val); break; case INT: snprintf(buf, sizeof(buf), "%"PRId64, v->u.int_val); add_param(params_node, "string", buf); break; case FLOAT: snprintf(buf, sizeof(buf), "%lf", v->u.float_val); add_param(params_node, "double", buf); break; case BOOL: add_param(params_node, "boolean", v->u.bool_val ? "1" : "0"); break; case VOID: add_param(params_node, "string", ""); break; case ENUM: add_param(params_node, "string", v->type->enum_marshaller(v->u.enum_val)); break; case SET: { const struct abstract_type *member_type = v->type->child; arbitrary_set *set_val = v->u.struct_val; abstract_value v; xmlNode *data_node = add_param_struct(params_node); for (size_t i = 0; i < set_val->size; i++) { switch (member_type->typename) { case STRING: v.u.string_val = (char *)set_val->contents[i]; make_body_add_type(member_type->typename, &v, data_node); break; default: assert(false); } } } break; case STRUCT: { size_t member_count = v->type->member_count; xmlNode *struct_node = add_param_struct(params_node); for (size_t i = 0; i < member_count; i++) { const struct struct_member *mem = v->type->members + i; const char *key = mem->key; void *struct_value = v->u.struct_val; add_struct_value(mem->type, struct_value + mem->offset, add_struct_member, key, struct_node); } } break; case MAP: { const struct struct_member *member = v->type->members; arbitrary_map *map_val = v->u.struct_val; xmlNode *param_node = add_param_struct(params_node); for (size_t i = 0; i < map_val->size; i++) { enum abstract_typename typename_key = member[0].type->typename; enum abstract_typename typename_val = member[1].type->typename; int offset_key = member[0].offset; int offset_val = member[1].offset; int struct_size = v->type->struct_size; switch (typename_key) { case STRING: { char **addr = (void *)(map_val + 1) + (i * struct_size) + offset_key; char *key = *addr; switch (typename_val) { case STRING: { char *val; addr = (void *)(map_val + 1) + (i * struct_size) + offset_val; val = *addr; add_struct_member(param_node, key, "string", val); break; } default: assert(false); } break; } default: assert(false); } } } break; default: assert(false); }}static char *make_body(const char *method_name, abstract_value params[], int param_count){ xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); xmlNode *params_node, *methodCall = xmlNewNode(NULL, BAD_CAST "methodCall"); xmlBufferPtr buffer; xmlSaveCtxtPtr save_ctxt; xmlChar *content; xmlDocSetRootElement(doc, methodCall); xmlNewChild(methodCall, NULL, BAD_CAST "methodName", BAD_CAST method_name); params_node = xmlNewChild(methodCall, NULL, BAD_CAST "params", NULL); for (int p = 0; p < param_count; p++) { abstract_value *v = params + p; make_body_add_type(v->type->typename, v, params_node); } buffer = xmlBufferCreate(); save_ctxt = xmlSaveToBuffer(buffer, NULL, XML_SAVE_NO_XHTML); if (xmlSaveDoc(save_ctxt, doc) == -1) { return NULL; } xmlFreeDoc(doc); xmlSaveClose(save_ctxt); content = xmlStrdup(xmlBufferContent(buffer)); xmlBufferFree(buffer); return (char *)content;}static voidadd_struct_value(const struct abstract_type *type, void *value, void (*adder)(xmlNode *node, const char *key, const char *type, const char *val), const char *key, xmlNode *node){ char buf[20]; switch (type->typename) { case REF: case STRING: case INT: case ENUM: { const char *val_as_string = get_val_as_string(type, value, buf, sizeof(buf)); adder(node, key, "string", val_as_string); } break; case FLOAT: { double val = *(double *)value; snprintf(buf, sizeof(buf), "%lf", val); adder(node, key, "double", buf); } break; case BOOL: { bool val = *(bool *)value; adder(node, key, "boolean", val ? "1" : "0"); } break; case SET: { const struct abstract_type *member_type = type->child; size_t member_size = size_of_member(member_type); arbitrary_set *set_val = *(arbitrary_set **)value; if (set_val != NULL) { xmlNode *data_node = add_struct_array(node, key); for (size_t i = 0; i < set_val->size; i++) { void *member_value = (char *)set_val->contents + (i * member_size); add_struct_value(member_type, member_value, add_unnamed_value, NULL, data_node); } } } break; case STRUCT: { assert(false); /* XXX Nested structures aren't supported yet, but fortunately we don't need them, because we don't have any "deep create" calls. This will need to be fixed. */ } break; case MAP: { size_t member_size = type->struct_size; const struct abstract_type *l_type = type->members[0].type; const struct abstract_type *r_type = type->members[1].type; int l_offset = type->members[0].offset; int r_offset = type->members[1].offset; arbitrary_map *map_val = *(arbitrary_map **)value; if (map_val != NULL) { xmlNode *struct_node = add_nested_struct(node, key); for (size_t i = 0; i < map_val->size; i++) { void *contents = (void *)map_val->contents; void *l_value = contents + (i * member_size) + l_offset; void *r_value = contents + (i * member_size) + r_offset; const char *l_value_as_string = get_val_as_string(l_type, l_value, buf, sizeof(buf)); add_struct_value(r_type, r_value, add_struct_member, l_value_as_string, struct_node); } } } break; default: assert(false); }}static const char *get_val_as_string(const struct abstract_type *type, void *value, char *buf, size_t bufsize){ switch (type->typename) { case REF: { arbitrary_record_opt *val = *(arbitrary_record_opt **)value; if (val != NULL) { if (val->is_record) { return val->u.record->handle; } else { return val->u.handle; } } else { return NULL; } } break; case STRING: { return *(char **)value; } break; case INT: { int64_t val = *(int64_t *)value; snprintf(buf, bufsize, "%"PRId64, val); return buf; } break; case ENUM: { int val = *(int *)value; return type->enum_marshaller(val); } break; default: assert(false); }}static xmlNode *add_container(xmlNode *parent, const char *name){ return xmlNewChild(parent, NULL, BAD_CAST name, NULL);}static voidadd_param(xmlNode *params_node, const char *type, const char *value){ xmlNode *param_node = add_container(params_node, "param"); add_value(param_node, type, value);}static voidadd_value(xmlNode *parent, const char *type, const char *value){ xmlNode *value_node = add_container(parent, "value"); xmlNewChild(value_node, NULL, BAD_CAST type, BAD_CAST value);}static voidadd_unnamed_value(xmlNode *parent, const char *name, const char *type, const char *value){ (void)name; add_value(parent, type, value);}static xmlNode *add_param_struct(xmlNode *params_node){ xmlNode *param_node = add_container(params_node, "param"); xmlNode *value_node = add_container(param_node, "value"); return xmlNewChild(value_node, NULL, BAD_CAST "struct", NULL);}static voidadd_struct_member(xmlNode *struct_node, const char *name, const char *type, const char *value){ xmlNode *member_node = add_container(struct_node, "member"); xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name); add_value(member_node, type, value);}static xmlNode *add_struct_array(xmlNode *struct_node, const char *name){ xmlNode *member_node = add_container(struct_node, "member"); xmlNode *value_node, *array_node; xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name); value_node = add_container(member_node, "value"); array_node = add_container(value_node, "array"); return add_container(array_node, "data");}static xmlNode *add_nested_struct(xmlNode *struct_node, const char *name){ xmlNode *member_node = add_container(struct_node, "member"); xmlNode *value_node; xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name); value_node = add_container(member_node, "value"); return add_container(value_node, "struct");}int xen_enum_lookup_(xen_session *session, const char *str, const char **lookup_table, int n){ if (str != NULL) { for (int i = 0; i < n; i++) { if (0 == strcmp(str, lookup_table[i])) { return i; } } } server_error_2(session, "Bad enum string", str); return 0;}char *xen_strdup_(const char *in){ char *result = malloc(strlen(in) + 1); strcpy(result, in); return result;}const abstract_type abstract_type_string = { .typename = STRING };const abstract_type abstract_type_int = { .typename = INT };const abstract_type abstract_type_float = { .typename = FLOAT };const abstract_type abstract_type_bool = { .typename = BOOL };const abstract_type abstract_type_datetime = { .typename = DATETIME };const abstract_type abstract_type_ref = { .typename = REF };const abstract_type abstract_type_string_set = { .typename = SET, .child = &abstract_type_string };const abstract_type abstract_type_ref_set = { .typename = SET, .child = &abstract_type_ref };static const struct struct_member string_string_members[] ={ { .type = &abstract_type_string, .offset = offsetof(xen_string_string_map_contents, key) }, { .type = &abstract_type_string, .offset = offsetof(xen_string_string_map_contents, val) }};const abstract_type abstract_type_string_string_map = { .typename = MAP, .struct_size = sizeof(xen_string_string_map_contents), .members = string_string_members };static struct struct_member int_float_members[] ={ { .type = &abstract_type_int, .offset = offsetof(xen_int_float_map_contents, key) }, { .type = &abstract_type_float, .offset = offsetof(xen_int_float_map_contents, val) }};const abstract_type abstract_type_int_float_map = { .typename = MAP, .struct_size = sizeof(xen_int_float_map_contents), .members = int_float_members };static struct struct_member int_int_members[] ={ { .type = &abstract_type_int, .offset = offsetof(xen_int_int_map_contents, key) }, { .type = &abstract_type_int, .offset = offsetof(xen_int_int_map_contents, val) }};const abstract_type abstract_type_int_int_map = { .typename = MAP, .struct_size = sizeof(xen_int_int_map_contents), .members = int_int_members };static struct struct_member int_string_set_members[] ={ { .type = &abstract_type_int, .offset = offsetof(xen_int_string_set_map_contents, key) }, { .type = &abstract_type_string_set, .offset = offsetof(xen_int_string_set_map_contents, val) }};const abstract_type abstract_type_int_string_set_map = { .typename = MAP, .struct_size = sizeof(xen_int_string_set_map_contents), .members = int_string_set_members };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -