📄 xen_common.c
字号:
{ int result = 0; xmlNode *cur = n->children; while (cur != NULL) { if (0 == strcmp((char *)cur->name, name)) { result++; } cur = cur->next; } return result;}static void destring(xen_session *s, xmlChar *name, const abstract_type *type, void *value){ switch (type->typename) { case STRING: *((char **)value) = xen_strdup_((const char *)name); break; case INT: *((int64_t *)value) = atoll((const char *)name); break; case FLOAT: *((double *)value) = atof((const char *)name); break; default: server_error(s, "Invalid Map key type"); }}/** * result_type : STRING => value : char **, the char * is yours. * result_type : ENUM => value : int * * result_type : INT => value : int64_t * * result_type : FLOAT => value : double * * result_type : BOOL => value : bool * * result_type : DATETIME => value : time_t * * result_type : SET => value : arbitrary_set **, the set is yours. * result_type : MAP => value : arbitrary_map **, the map is yours. * result_type : OPT => value : arbitrary_record_opt **, * the record is yours, the handle is * filled. * result_type : STRUCT => value : void **, the void * is yours. */static void parse_into(xen_session *s, xmlNode *value_node, const abstract_type *result_type, void *value, int slot){ if (result_type == NULL) { xmlChar *string = string_from_value(value_node, "string"); if (string == NULL || strcmp((char *)string, "")) { server_error(s, "Expected Void from the server, but didn't get it"); } else { free(string); } return; } switch (result_type->typename) { case STRING: { xmlChar *string = string_from_value(value_node, "string"); if (string == NULL) { server_error( s, "Expected a String from the server, but didn't get one"); } else { ((char **)value)[slot] = xen_strdup_((const char *)string); free(string); } } break; case ENUM: { xmlChar *string = string_from_value(value_node, "string"); if (string == NULL) {#if PERMISSIVE fprintf(stderr, "Expected an Enum from the server, but didn't get one\n"); ((int *)value)[slot] = 0;#else server_error( s, "Expected an Enum from the server, but didn't get one");#endif } else { ((int *)value)[slot] = result_type->enum_demarshaller(s, (const char *)string); free(string); } } break; case INT: { xmlChar *string = string_from_value(value_node, "string"); if (string == NULL) { server_error( s, "Expected an Int from the server, but didn't get one"); } else { ((int64_t *)value)[slot] = (int64_t)atoll((char *)string); free(string); } } break; case FLOAT: { xmlChar *string = string_from_value(value_node, "double"); if (string == NULL) {#if PERMISSIVE fprintf(stderr, "Expected a Float from the server, but didn't get one\n"); ((double *)value)[slot] = 0.0;#else server_error( s, "Expected a Float from the server, but didn't get one");#endif } else { ((double *)value)[slot] = atof((char *)string); free(string); } } break; case BOOL: { xmlChar *string = string_from_value(value_node, "boolean"); if (string == NULL) {#if PERMISSIVE fprintf(stderr, "Expected a Bool from the server, but didn't get one\n"); ((bool *)value)[slot] = false;#else server_error( s, "Expected a Bool from the server, but didn't get one");#endif } else { ((bool *)value)[slot] = (0 == strcmp((char *)string, "1")); free(string); } } break; case DATETIME: { xmlChar *string = string_from_value(value_node, "dateTime.iso8601"); if (string == NULL) { server_error( s, "Expected an DateTime from the server but didn't get one"); } else { struct tm tm; memset(&tm, 0, sizeof(tm)); strptime((char *)string, "%Y%m%dT%H:%M:%S", &tm); ((time_t *)value)[slot] = (time_t)mktime(&tm); free(string); } } break; case SET: { if (!is_container_node(value_node, "value") || !is_container_node(value_node->children, "array")) { server_error(s, "Expected Set from the server, but didn't get it"); } else { arbitrary_set *set; xmlNode *cur, *data_node = value_node->children->children; int i, n = count_children(data_node, "value"); const abstract_type *member_type = result_type->child; size_t member_size = size_of_member(member_type); set = calloc(1, sizeof(arbitrary_set) + member_size * n); set->size = n; i = 0; cur = data_node->children; while (cur != NULL) { if (0 == strcmp((char *)cur->name, "value")) { parse_into(s, cur, member_type, set->contents, i); i++; } cur = cur->next; } ((arbitrary_set **)value)[slot] = set; } } break; case MAP: { if (!is_container_node(value_node, "value") || value_node->children->type != XML_ELEMENT_NODE || 0 != strcmp((char *)value_node->children->name, "struct")) { server_error(s, "Expected Map from the server, but didn't get it"); } else { arbitrary_map *map; xmlNode *cur, *struct_node = value_node->children; int i, n = count_children(struct_node, "member"); size_t struct_size = result_type->struct_size; const struct struct_member *key_member = result_type->members; const struct struct_member *val_member = result_type->members + 1; map = calloc(1, sizeof(arbitrary_map) + struct_size * n); map->size = n; i = 0; cur = struct_node->children; while (cur != NULL) { if (0 == strcmp((char *)cur->name, "member")) { xmlChar *name; if (cur->children == NULL || cur->last == cur->children) { server_error(s, "Malformed Map"); free(map); return; } name = string_from_name(cur); if (name == NULL) { server_error(s, "Malformed Map"); free(map); return; } destring(s, name, key_member->type, ((void *)(map + 1)) + (i * struct_size) + key_member->offset); xmlFree(name); if (!s->ok) { free(map); return; } parse_structmap_value(s, cur, val_member->type, ((void *)(map + 1)) + (i * struct_size) + val_member->offset); if (!s->ok) { free(map); return; } i++; } cur = cur->next; } ((arbitrary_map **)value)[slot] = map; } } break; case STRUCT: { if (!is_container_node(value_node, "value") || value_node->children->type != XML_ELEMENT_NODE || 0 != strcmp((char *)value_node->children->name, "struct") || value_node->children->children == NULL) { server_error(s, "Expected Map from the server, but didn't get it"); } else { xmlNode *struct_node = value_node->children; void *result = calloc(1, result_type->struct_size); xmlNode *cur = struct_node->children; size_t member_count = result_type->member_count; const struct_member **checklist = malloc(sizeof(const struct_member *) * member_count); int seen_count = 0; while (cur != NULL) { if (0 == strcmp((char *)cur->name, "member")) { xmlChar *name; if (cur->children == NULL || cur->last == cur->children) { server_error(s, "Malformed Struct"); free(result); free(checklist); return; } name = string_from_name(cur); if (name == NULL) { server_error(s, "Malformed Struct"); free(result); free(checklist); return; } for (size_t i = 0; i < member_count; i++) { const struct_member *mem = result_type->members + i; if (0 == strcmp((char *)name, mem->key)) { parse_structmap_value(s, cur, mem->type, result + mem->offset); checklist[seen_count] = mem; seen_count++; break; } } /* Note that we're skipping unknown fields implicitly. This means that we'll be forward compatible with new servers. */ xmlFree(name); if (!s->ok) { free(result); free(checklist); return; } } cur = cur->next; } /* Check that we've filled all fields. */ for (size_t i = 0; i < member_count; i++) { const struct_member *mem = result_type->members + i; int j; for (j = 0; j < seen_count; j++) { if (checklist[j] == mem) { break; } } if (j == seen_count) {#if PERMISSIVE fprintf(stderr, "Struct did not contain expected field %s.\n", mem->key);#else server_error_2(s, "Struct did not contain expected field", mem->key); free(result); free(checklist); return;#endif } } free(checklist); ((void **)value)[slot] = result; } } break; case REF: { arbitrary_record_opt *record_opt = calloc(1, sizeof(arbitrary_record_opt)); record_opt->is_record = false; parse_into(s, value_node, &abstract_type_string, &(record_opt->u.handle), 0); ((arbitrary_record_opt **)value)[slot] = record_opt; } break; default: assert(false); }}static size_t size_of_member(const abstract_type *type){ switch (type->typename) { case STRING: return sizeof(char *);/* case INT: return sizeof(int64_t); case FLOAT: return sizeof(double); case BOOL: return sizeof(bool);*/ case ENUM: return sizeof(int); case REF: return sizeof(arbitrary_record_opt *); case STRUCT: return type->struct_size; default: assert(false); }}static void parse_structmap_value(xen_session *s, xmlNode *n, const abstract_type *type, void *value){ xmlNode *cur = n->children; while (cur != NULL) { if (0 == strcmp((char *)cur->name, "value")) { parse_into(s, cur, type, value, 0); return; } cur = cur->next; } server_error(s, "Missing value in Map/Struct");}static void parse_fault(xen_session *session, xmlXPathContextPtr xpathCtx){ xmlNode *fault_node0, *fault_node1; xmlChar *fault_code_str, *fault_string_str; char **strings; xmlXPathObjectPtr xpathObj = xmlXPathCompiledEval(faultPath, xpathCtx); if (xpathObj == NULL) { server_error(session, "Method response is neither result nor fault"); return; } if (xpathObj->type != XPATH_NODESET || xpathObj->nodesetval->nodeNr != 2) { xmlXPathFreeObject(xpathObj); server_error(session, "Method response is neither result nor fault"); return; } fault_node0 = xpathObj->nodesetval->nodeTab[0]; fault_node1 = xpathObj->nodesetval->nodeTab[1]; fault_code_str = string_from_value(fault_node0, "int"); if (fault_code_str == NULL) { fault_code_str = string_from_value(fault_node0, "i4"); } if (fault_code_str == NULL) { xmlXPathFreeObject(xpathObj); server_error(session, "Fault code is malformed"); return; } fault_string_str = string_from_value(fault_node1, "string"); if (fault_string_str == NULL) { xmlFree(fault_code_str); xmlXPathFreeObject(xpathObj); server_error(session, "Fault string is malformed"); return; } strings = malloc(3 * sizeof(char *)); strings[0] = xen_strdup_("FAULT"); strings[1] = xen_strdup_((char *)fault_code_str); strings[2] = xen_strdup_((char *)fault_string_str); session->ok = false; session->error_description = strings; session->error_description_count = 3; xmlFree(fault_code_str); xmlFree(fault_string_str); xmlXPathFreeObject(xpathObj);}static void parse_failure(xen_session *session, xmlNode *node){ abstract_type error_description_type = { .typename = SET, .child = &abstract_type_string }; arbitrary_set *error_descriptions; parse_into(session, node, &error_description_type, &error_descriptions, 0); if (session->ok) { char **c, **strings; int n; session->ok = false; c = (char **)error_descriptions->contents; n = error_descriptions->size; strings = malloc(n * sizeof(char *)); for (int i = 0; i < n; i++) { strings[i] = c[i]; } session->error_description_count = n; session->error_description = strings; } free(error_descriptions);}/** * Parameters as for xen_call_() above. */static void parse_result(xen_session *session, const char *result, const abstract_type *result_type, void *value){ xmlDocPtr doc = xmlReadMemory(result, strlen(result), "", NULL, XML_PARSE_NONET);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -