/** * MR_BITMASK type saving handler. Look up type descriptor and save as * stringified bitmask value or as integer otherwise. * @param ptrdes descriptor of the saved field * @param bitmask_or_delimiter delimiter for OR statement * @return stringified enum value */ char * mr_stringify_bitmask (mr_ptrdes_t * ptrdes, char * bitmask_or_delimiter) { int i, count; uint64_t value = 0; char * str = NULL; mr_td_t * tdp = mr_get_td_by_name (ptrdes->fd.type); /* look up for type descriptor */ /* check whether type descriptor was found */ if (NULL == tdp) { MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_NO_TYPE_DESCRIPTOR, ptrdes->fd.type); return (mr_stringify_uint (ptrdes)); } if (MR_TYPE_ENUM != tdp->mr_type) { MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_TYPE_NOT_ENUM, ptrdes->fd.type); return (mr_stringify_uint (ptrdes)); } value = mr_get_enum_value (tdp, ptrdes->data); if (0 == value) { mr_fd_t * fdp = mr_get_enum_by_value (tdp, value); return (MR_STRDUP (fdp && fdp->name.str ? fdp->name.str : "0")); } /* decompose value on bitmask */ count = tdp->fields.size / sizeof (tdp->fields.data[0]); for (i = 0; i < count; ++i) { mr_fd_t * fdp = tdp->fields.data[i].fdp; if ((value & fdp->param.enum_value) && !(~value & fdp->param.enum_value)) { if (NULL == str) str = MR_STRDUP (fdp->name.str); else str = mr_decompose_bitmask_add (str, bitmask_or_delimiter, fdp->name.str); if (NULL == str) break; value &= ~fdp->param.enum_value; } if (0 == value) break; } if (value != 0) { /* save non-matched part as integer */ mr_ptrdes_t ptrdes = { .data = &value, }; char * number = mr_stringify_uint64_t (&ptrdes); if (number != NULL) { str = mr_decompose_bitmask_add (str, bitmask_or_delimiter, number); MR_FREE (number); } MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_SAVE_BITMASK, value); }
int xml2_load (xmlNodePtr node, mr_ra_mr_ptrdes_t * ptrs) { int idx = mr_add_ptr_to_list (ptrs); xmlNodePtr node_; char * content = NULL; char * property = NULL; if (idx < 0) return (idx); /* handle REF_IDX property */ property = (char*)xmlGetProp (node, (unsigned char*)MR_REF_IDX); if (property) { if (1 != sscanf (property, "%" SCNd32, &ptrs->ra.data[idx].idx)) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_READ_REF, property); ptrs->ra.data[idx].flags.is_referenced = MR_TRUE; xmlFree (property); } /* handle REF property */ property = (char*)xmlGetProp (node, (unsigned char*)MR_REF); if (property) { if (1 != sscanf (property, "%" SCNd32, &ptrs->ra.data[idx].ref_idx)) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_READ_REF, property); xmlFree (property); } /* handle REF_CONTENT property */ property = (char*)xmlGetProp (node, (unsigned char*)MR_REF_CONTENT); if (property) { if (1 != sscanf (property, "%" SCNd32, &ptrs->ra.data[idx].ref_idx)) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_READ_REF, property); else ptrs->ra.data[idx].flags.is_content_reference = MR_TRUE; xmlFree (property); } property = (char*)xmlGetProp (node, (unsigned char*)MR_ISNULL); if (property) { ptrs->ra.data[idx].flags.is_null= MR_TRUE; xmlFree (property); } for (node_ = node->xmlChildrenNode; node_ && !content; node_ = node_->next) content = (char*)XML_GET_CONTENT (node_); ptrs->ra.data[idx].mr_value.value_type = MR_VT_UNKNOWN; ptrs->ra.data[idx].mr_value.vt_string = content ? MR_STRDUP (content) : MR_STRDUP (""); ptrs->ra.data[idx].fd.name.str = MR_STRDUP ((char*)node->name); /* loop on subnodes */ for (node_ = node->xmlChildrenNode; node_; node_ = node_->next) if (XML_ELEMENT_NODE == node_->type) mr_add_child (idx, xml2_load (node_, ptrs), ptrs); return (idx); }
mr_status_t mr_value_cast (mr_value_type_t value_type, mr_value_t * value) { mr_status_t status = MR_SUCCESS; mr_value_id (value); switch (value_type) { case MR_VT_INT: MR_VALUE_CAST (vt_int); break; case MR_VT_FLOAT: MR_VALUE_CAST (vt_float); break; case MR_VT_COMPLEX: MR_VALUE_CAST (vt_complex); break; default: MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_WRONG_RESULT_TYPE); status = MR_FAILURE; break; } return (status); }
/** * Read enum value from string * @param data pointer on place to save value * @param str string with enum * @return A pointer on the rest of parsed string */ static char * mr_get_enum (char * str, uint64_t * data) { char * name = str; int size; while (isalnum (*str) || (*str == '_')) ++str; size = str - name; { char name_[size + 1]; memcpy (name_, name, size); name_[size] = 0; if (0 == strcmp ("FALSE", name_)) *data = FALSE; else if (0 == strcmp ("TRUE", name_)) *data = TRUE; else { mr_fd_t * fdp = mr_get_enum_by_name (name_); if (NULL == fdp) { MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_UNKNOWN_ENUM, name_); return (NULL); } *data = fdp->param.enum_value; } } return (str); }
static char * mr_load_long_double (char * str, long double * data) { int offset; if (1 != sscanf (str, "%Lg%n", data, &offset)) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_LONG_DOUBLE, str); return (NULL); } return (&str[offset]); }
bool mr_value_is_zero (mr_value_t * value) { switch (value->value_type) { case MR_VT_INT: return (0 == value->vt_int); case MR_VT_FLOAT: return (0 == value->vt_float); case MR_VT_COMPLEX: return (0 == value->vt_complex); default: MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_WRONG_RESULT_TYPE); } return (FALSE); }
/** * MR_ENUM type saving handler. Look up enum descriptor and save as * stringified enum value or as integer otherwise. * @param ptrdes descriptor of the saved field * @return stringified enum value */ char * mr_stringify_enum (mr_ptrdes_t * ptrdes) { mr_td_t * tdp = mr_get_td_by_name (ptrdes->fd.type); /* look up for type descriptor */ /* check whether type descriptor was found */ if (NULL == tdp) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_NO_TYPE_DESCRIPTOR, ptrdes->fd.type); else if (MR_TYPE_ENUM != tdp->mr_type) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_TYPE_NOT_ENUM, ptrdes->fd.type); else { int64_t value = mr_get_enum_value (tdp, ptrdes->data); mr_fd_t * fdp = mr_get_enum_by_value (tdp, value); if (fdp && fdp->name.str) return (MR_STRDUP (fdp->name.str)); MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_SAVE_ENUM, value, tdp->type.str, ptrdes->fd.name.str); ptrdes->fd.size = tdp->size_effective; } /* save as integer otherwise */ return (mr_stringify_uint (ptrdes)); }
/** * Read int value from string (may be as ENUM) * @param str string with int * @param data pointer on place to save int * @return A pointer on the rest of parsed string */ static char * mr_get_int (char * str, uint64_t * data) { int offset; while (isspace (*str)) ++str; if (isalpha (*str)) str = mr_get_enum (str, data); else if ('0' == *str) { if ('x' == str[1]) { if (1 != sscanf (str, "%" SCNx64 "%n", data, &offset)) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_INT, str); return (NULL); } } else { if (1 != sscanf (str, "%" SCNo64 "%n", data, &offset)) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_INT, str); return (NULL); } } str += offset; } else { if ((1 == sscanf (str, "%" SCNu64 "%n", data, &offset)) || (1 == sscanf (str, "%" SCNd64 "%n", data, &offset))) str += offset; else { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_INT, str); return (NULL); } } return (str); }
static char * mr_load_complex_long_double (char * str, complex long double * x) { int offset; long double real, imag; if (2 != sscanf (str, "%Lg + %Lgi%n", &real, &imag, &offset)) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_COMPLEX_LONG_DOUBLE, str); return (NULL); } __real__ * x = real; __imag__ * x = imag; return (&str[offset]); }
/** * Stringify integer value. * @param ptrdes descriptor of the saved field * @return stringified enum value */ static char * mr_stringify_uint (mr_ptrdes_t * ptrdes) { switch (ptrdes->fd.size) { case sizeof (uint8_t): return (mr_stringify_uint8_t (ptrdes)); case sizeof (uint16_t): return (mr_stringify_uint16_t (ptrdes)); case sizeof (uint32_t): return (mr_stringify_uint32_t (ptrdes)); case sizeof (uint64_t): return (mr_stringify_uint64_t (ptrdes)); default: MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_INT_OF_UNKNOWN_SIZE, ptrdes->fd.size); return (MR_STRDUP ("0")); } }
static mr_status_t mr_load_var (mr_type_t mr_type, char * str, void * var) { if ((NULL == str) || (NULL == var)) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNEXPECTED_NULL_POINTER); return (MR_FAILURE); } switch (mr_type) { case MR_TYPE_INT64: case MR_TYPE_UINT64: str = mr_load_bitmask (str, var); break; case MR_TYPE_LONG_DOUBLE: str = mr_load_long_double (str, var); break; case MR_TYPE_COMPLEX_LONG_DOUBLE: str = mr_load_complex_long_double (str, var); break; default: break; } if (NULL == str) return (MR_FAILURE); while (isspace (*str)) ++str; if (*str != 0) { MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNEXPECTED_DATA_AT_THE_END, str); return (MR_FAILURE); } return (MR_SUCCESS); }
mr_status_t mr_value_neg (mr_value_t * value) { mr_value_id (value); switch (value->value_type) { case MR_VT_INT: value->vt_int = -value->vt_int; break; case MR_VT_FLOAT: value->vt_float = -value->vt_float; break; case MR_VT_COMPLEX: value->vt_complex = -value->vt_complex; break; default: MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_WRONG_RESULT_TYPE); return (MR_FAILURE); } return (MR_SUCCESS); }
static char * mr_decompose_bitmask_add (char * str, char * bitmask_or_delimiter, char * token) { char * str_ = MR_REALLOC (str, strlen (str) + strlen (bitmask_or_delimiter) + strlen (token) + 1); if (NULL == str_) { MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); MR_FREE (str); } else { strcat (str_, bitmask_or_delimiter); strcat (str_, token); } return (str_); }
/** * MR_BITMASK type saving handler. Look up type descriptor and save as * stringified bitmask value or as integer otherwise. * @param idx an index of node in ptrs * @param ptrs resizeable array with pointers descriptors * @return stringified enum value */ static char * scm_save_bitmask (int idx, mr_ra_mr_ptrdes_t * ptrs) { char * str = mr_stringify_bitmask (&ptrs->ra.data[idx], MR_SCM_BITMASK_OR_DELIMITER); if (str) { char * str_ = MR_MALLOC ((sizeof (MR_SCM_BITMASK_TEMPLATE) - 1) + (strlen (str) - 2) + 1); if (NULL == str_) { MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); return (NULL); } sprintf (str_, MR_SCM_BITMASK_TEMPLATE, str); MR_FREE (str); str = str_; } return (str); }
/** * XML quote function. Escapes XML special characters. * @param str input string * @return XML quoted string */ static char * xml_quote_string (char * str) { int length = 0; char * str_; if (NULL == str) return (NULL); for (str_ = str; *str_; ++str_) if (map[(unsigned char)*str_]) length += strlen (map[(unsigned char)*str_]); else if (isprint (*str_)) ++length; else length += sizeof (XML_NONPRINT_ESC) - 1; str_ = MR_MALLOC (length + 1); if (NULL == str) { MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); return (NULL); } length = 0; for (; *str; ++str) if (map[(unsigned char)*str]) { strcpy (&str_[length], map[(unsigned char)*str]); length += strlen (&str_[length]); } else if (isprint (*str)) str_[length++] = *str; else { sprintf (&str_[length], XML_NONPRINT_ESC, (int)(unsigned char)*str); length += strlen (&str_[length]); } str_[length] = 0; return (str_); }
static void mr_value_id (mr_value_t * value) { if (MR_VT_ID != value->value_type) return; value->value_type = MR_VT_INT; if (NULL == value->vt_string) value->vt_int = 0; else { mr_fd_t * fdp = mr_get_enum_by_name (value->vt_string); __typeof__ (value->vt_int) vt_int = 0; if (NULL == fdp) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_UNKNOWN_ENUM, value->vt_string); else vt_int = fdp->param.enum_value; MR_FREE (value->vt_string); value->vt_int = vt_int; } }
/** * Quote string. * @param str string pointer * @param quote quote character * @return quoted string */ static char * scm_quote_string (char * str, char quote) { int length = 0; char * str_; char * ptr; for (ptr = str; *ptr; ++ptr) { if ((quote == *ptr) || ('\\' == *ptr)) ++length; if (!isprint (*ptr)) length += 4; ++length; } str_ = MR_MALLOC (length + 3); if (NULL == str_) { MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); return (NULL); } length = 0; str_[length++] = quote; for (ptr = str; *ptr; ++ptr) { if ((quote == *ptr) || ('\\' == *ptr)) str_[length++] = '\\'; if (isprint (*ptr)) str_[length++] = *ptr; else { str_[length++] = '\\'; sprintf (&str_[length], "x%02x;", (int)(unsigned char)*ptr); length += 4; } } str_[length++] = quote; str_[length++] = 0; return (str_); }
/** * XML unquote function. Replace XML special characters aliases on a source characters. * @param str input string * @param length length of the input string * @return XML unquoted string */ char * xml_unquote_string (mr_substr_t * substr) { char * str_ = MR_MALLOC (substr->length + 1); int length_ = 0; int i, j; static int inited = 0; static char map_c[ESC_CHAR_MAP_SIZE]; static char * map_cp[ESC_CHAR_MAP_SIZE]; static int map_s[ESC_CHAR_MAP_SIZE]; static int map_size = 0; if (0 == inited) { for (i = 0; i < ESC_CHAR_MAP_SIZE; ++i) if (map[i]) { int size = strlen (map[i]); if (size > 1) { map_c[map_size] = i; map_cp[map_size] = map[i]; map_s[map_size] = size; ++map_size; } } inited = !0; } if (NULL == str_) { MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); return (NULL); } for (j = 0; j < substr->length; ++j) if (substr->str[j] != '&') str_[length_++] = substr->str[j]; else { char esc[ESC_SIZE]; strncpy (esc, &substr->str[j], sizeof (esc) - 1); if ('#' == substr->str[j + 1]) { int32_t code = 0; int size = 0; if (1 != sscanf (&substr->str[j], XML_NONPRINT_ESC "%n", &code, &size)) MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_WRONG_XML_ESC, esc); else { j += size - 1; /* one more +1 in the loop */ str_[length_++] = code; } } else { for (i = 0; i < map_size; ++i) if (0 == strncasecmp (&substr->str[j], map_cp[i], map_s[i])) { str_[length_++] = map_c[i]; j += map_s[i] - 1; /* one more increase in the loop */ break; } if (i >= map_size) { MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_UNKNOWN_XML_ESC, esc); str_[length_++] = substr->str[j]; } } } str_[length_] = 0; return (str_); }