diff --git a/src/sdp-xml.c b/src/sdp-xml.c
index 7d5f626..262b8e7 100644
--- a/src/sdp-xml.c
+++ b/src/sdp-xml.c
#define STRBUFSIZE 1024
#define MAXINDENT 64
+struct sdp_xml_data {
+ char *text; /* Pointer to the current buffer */
+ int size; /* Size of the current buffer */
+ sdp_data_t *data; /* The current item being built */
+ struct sdp_xml_data *next; /* Next item on the stack */
+ char type; /* 0 = Text or Hexadecimal */
+ char *name; /* Name, optional in the dtd */
+ /* TODO: What is it used for? */
+};
+
struct context_data {
sdp_record_t *record;
sdp_data_t attr_data;
return unit_size;
}
-static void element_start(GMarkupParseContext *context,
- const gchar *element_name, const gchar **attribute_names,
- const gchar **attribute_values, gpointer user_data, GError **err)
-{
- struct context_data *ctx_data = user_data;
+#define DEFAULT_XML_DATA_SIZE 1024
- if (!strcmp(element_name, "record"))
- return;
+static struct sdp_xml_data *sdp_xml_data_alloc(void)
+{
+ struct sdp_xml_data *elem;
- if (!strcmp(element_name, "attribute")) {
- int i;
- for (i = 0; attribute_names[i]; i++) {
- if (!strcmp(attribute_names[i], "id")) {
- ctx_data->attr_id = strtol(attribute_values[i], 0, 0);
- break;
- }
- }
- DBG("New attribute 0x%04x", ctx_data->attr_id);
- return;
- }
+ elem = malloc(sizeof(struct sdp_xml_data));
+ if (!elem)
+ return NULL;
- if (ctx_data->stack_head) {
- struct sdp_xml_data *newelem = sdp_xml_data_alloc();
- newelem->next = ctx_data->stack_head;
- ctx_data->stack_head = newelem;
- } else {
- ctx_data->stack_head = sdp_xml_data_alloc();
- ctx_data->stack_head->next = NULL;
- }
+ memset(elem, 0, sizeof(struct sdp_xml_data));
- if (!strcmp(element_name, "sequence"))
- ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
- else if (!strcmp(element_name, "alternate"))
- ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
- else {
- int i;
- /* Parse value, name, encoding */
- for (i = 0; attribute_names[i]; i++) {
- if (!strcmp(attribute_names[i], "value")) {
- int curlen = strlen(ctx_data->stack_head->text);
- int attrlen = strlen(attribute_values[i]);
+ /* Null terminate the text */
+ elem->size = DEFAULT_XML_DATA_SIZE;
+ elem->text = malloc(DEFAULT_XML_DATA_SIZE);
+ elem->text[0] = '\0';
- /* Ensure we're big enough */
- while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) {
- sdp_xml_data_expand(ctx_data->stack_head);
- }
+ return elem;
+}
- memcpy(ctx_data->stack_head->text + curlen,
- attribute_values[i], attrlen);
- ctx_data->stack_head->text[curlen + attrlen] = '\0';
- }
+static struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem)
+{
+ char *newbuf;
- if (!strcmp(attribute_names[i], "encoding")) {
- if (!strcmp(attribute_values[i], "hex"))
- ctx_data->stack_head->type = 1;
- }
+ newbuf = malloc(elem->size * 2);
+ if (!newbuf)
+ return NULL;
- if (!strcmp(attribute_names[i], "name")) {
- ctx_data->stack_head->name = strdup(attribute_values[i]);
- }
- }
+ memcpy(newbuf, elem->text, elem->size);
+ elem->size *= 2;
+ free(elem->text);
- ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
- ctx_data->stack_head, ctx_data->record);
+ elem->text = newbuf;
- if (ctx_data->stack_head->data == NULL)
- error("Can't parse element %s", element_name);
- }
+ return elem;
}
-static void element_end(GMarkupParseContext *context,
- const gchar *element_name, gpointer user_data, GError **err)
+static sdp_data_t *sdp_xml_parse_uuid128(const char *data)
{
- struct context_data *ctx_data = user_data;
- struct sdp_xml_data *elem;
-
- if (!strcmp(element_name, "record"))
- return;
-
- if (!strcmp(element_name, "attribute")) {
- if (ctx_data->stack_head && ctx_data->stack_head->data) {
- int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
- ctx_data->stack_head->data);
- if (ret == -1)
- DBG("Could not add attribute 0x%04x",
- ctx_data->attr_id);
-
- ctx_data->stack_head->data = NULL;
- sdp_xml_data_free(ctx_data->stack_head);
- ctx_data->stack_head = NULL;
- } else {
- DBG("No data for attribute 0x%04x", ctx_data->attr_id);
- }
- return;
- }
-
- if (!ctx_data->stack_head || !ctx_data->stack_head->data) {
- DBG("No data for %s", element_name);
- return;
- }
+ uint128_t val;
+ unsigned int i, j;
- if (!strcmp(element_name, "sequence")) {
- ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
+ char buf[3];
- if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
- ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
- ctx_data->stack_head->data->dtd = SDP_SEQ32;
- } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
- ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
- ctx_data->stack_head->data->dtd = SDP_SEQ16;
- } else {
- ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
- }
- } else if (!strcmp(element_name, "alternate")) {
- ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
+ memset(&val, 0, sizeof(val));
- if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
- ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
- ctx_data->stack_head->data->dtd = SDP_ALT32;
- } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
- ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
- ctx_data->stack_head->data->dtd = SDP_ALT16;
- } else {
- ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
- }
- }
+ buf[2] = '\0';
- if (ctx_data->stack_head->next && ctx_data->stack_head->data &&
- ctx_data->stack_head->next->data) {
- switch (ctx_data->stack_head->next->data->dtd) {
- case SDP_SEQ8:
- case SDP_SEQ16:
- case SDP_SEQ32:
- case SDP_ALT8:
- case SDP_ALT16:
- case SDP_ALT32:
- ctx_data->stack_head->next->data->val.dataseq =
- sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq,
- ctx_data->stack_head->data);
- ctx_data->stack_head->data = NULL;
- break;
+ for (j = 0, i = 0; i < strlen(data);) {
+ if (data[i] == '-') {
+ i++;
+ continue;
}
- elem = ctx_data->stack_head;
- ctx_data->stack_head = ctx_data->stack_head->next;
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
- sdp_xml_data_free(elem);
+ val.data[j++] = strtoul(buf, 0, 16);
+ i += 2;
}
-}
-static GMarkupParser parser = {
- element_start, element_end, NULL, NULL, NULL
-};
+ return sdp_data_alloc(SDP_UUID128, &val);
+}
-sdp_record_t *sdp_xml_parse_record(const char *data, int size)
+static sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record)
{
- GMarkupParseContext *ctx;
- struct context_data *ctx_data;
- sdp_record_t *record;
+ sdp_data_t *ret;
+ char *endptr;
+ uint32_t val;
+ uint16_t val2;
+ int len;
- ctx_data = malloc(sizeof(*ctx_data));
- if (!ctx_data)
- return NULL;
+ len = strlen(data);
- record = sdp_record_alloc();
- if (!record) {
- free(ctx_data);
- return NULL;
+ if (len == 36) {
+ ret = sdp_xml_parse_uuid128(data);
+ goto result;
}
- memset(ctx_data, 0, sizeof(*ctx_data));
- ctx_data->record = record;
-
- ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);
+ val = strtoll(data, &endptr, 16);
- if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
- error("XML parsing error");
- g_markup_parse_context_free(ctx);
- sdp_record_free(record);
- free(ctx_data);
+ /* Couldn't parse */
+ if (*endptr != '\0')
return NULL;
+
+ if (val > USHRT_MAX) {
+ ret = sdp_data_alloc(SDP_UUID32, &val);
+ goto result;
}
- g_markup_parse_context_free(ctx);
+ val2 = val;
- free(ctx_data);
+ ret = sdp_data_alloc(SDP_UUID16, &val2);
- return record;
-}
+result:
+ if (record && ret)
+ sdp_pattern_add_uuid(record, &ret->val.uuid);
+ return ret;
+}
-static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level,
- void *data, void (*appender)(void *, const char *))
+static sdp_data_t *sdp_xml_parse_int(const char *data, uint8_t dtd)
{
- int i, hex;
- char buf[STRBUFSIZE];
- char indent[MAXINDENT];
+ char *endptr;
+ sdp_data_t *ret = NULL;
- if (!value)
- return;
+ switch (dtd) {
+ case SDP_BOOL:
+ {
+ uint8_t val = 0;
- if (indent_level >= MAXINDENT)
- indent_level = MAXINDENT - 2;
+ if (!strcmp("true", data))
+ val = 1;
+ else if (!strcmp("false", data))
+ val = 0;
+ else
+ return NULL;
- for (i = 0; i < indent_level; i++)
- indent[i] = '\t';
+ ret = sdp_data_alloc(dtd, &val);
+ break;
+ }
- indent[i] = '\0';
- buf[STRBUFSIZE - 1] = '\0';
+ case SDP_INT8:
+ {
+ int8_t val = strtoul(data, &endptr, 0);
- switch (value->dtd) {
- case SDP_DATA_NIL:
- appender(data, indent);
- appender(data, "<nil/>\n");
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_BOOL:
- appender(data, indent);
- appender(data, "<boolean value=\"");
- appender(data, value->val.uint8 ? "true" : "false");
- appender(data, "\" />\n");
+ case SDP_UINT8:
+ {
+ uint8_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_UINT8:
- appender(data, indent);
- appender(data, "<uint8 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%02x", value->val.uint8);
- appender(data, buf);
- appender(data, "\" />\n");
+ case SDP_INT16:
+ {
+ int16_t val = strtoul(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
case SDP_UINT16:
- appender(data, indent);
- appender(data, "<uint16 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uint16);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ {
+ uint16_t val = strtoul(data, &endptr, 0);
- case SDP_UINT32:
- appender(data, indent);
- appender(data, "<uint32 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uint32);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
- case SDP_UINT64:
- appender(data, indent);
- appender(data, "<uint64 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%016jx", value->val.uint64);
- appender(data, buf);
- appender(data, "\" />\n");
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_UINT128:
- appender(data, indent);
- appender(data, "<uint128 value=\"");
+ case SDP_INT32:
+ {
+ int32_t val = strtoul(data, &endptr, 0);
- for (i = 0; i < 16; i++) {
- sprintf(&buf[i * 2], "%02x",
- (unsigned char) value->val.uint128.data[i]);
- }
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
- appender(data, buf);
- appender(data, "\" />\n");
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_INT8:
- appender(data, indent);
- appender(data, "<int8 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int8);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ case SDP_UINT32:
+ {
+ uint32_t val = strtoul(data, &endptr, 0);
- case SDP_INT16:
- appender(data, indent);
- appender(data, "<int16 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int16);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
- case SDP_INT32:
- appender(data, indent);
- appender(data, "<int32 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int32);
- appender(data, buf);
- appender(data, "\" />\n");
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
case SDP_INT64:
- appender(data, indent);
- appender(data, "<int64 value=\"");
- snprintf(buf, STRBUFSIZE - 1, "%jd", value->val.int64);
- appender(data, buf);
- appender(data, "\" />\n");
+ {
+ int64_t val = strtoull(data, &endptr, 0);
+
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
+
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_INT128:
- appender(data, indent);
- appender(data, "<int128 value=\"");
+ case SDP_UINT64:
+ {
+ uint64_t val = strtoull(data, &endptr, 0);
- for (i = 0; i < 16; i++) {
- sprintf(&buf[i * 2], "%02x",
- (unsigned char) value->val.int128.data[i]);
- }
- appender(data, buf);
+ /* Failed to parse */
+ if ((endptr != data) && (*endptr != '\0'))
+ return NULL;
- appender(data, "\" />\n");
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_UUID16:
- appender(data, indent);
- appender(data, "<uuid value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uuid.value.uuid16);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ case SDP_INT128:
+ case SDP_UINT128:
+ {
+ uint128_t val;
+ int i = 0;
+ char buf[3];
- case SDP_UUID32:
- appender(data, indent);
- appender(data, "<uuid value=\"");
- snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uuid.value.uuid32);
- appender(data, buf);
- appender(data, "\" />\n");
- break;
+ buf[2] = '\0';
- case SDP_UUID128:
- appender(data, indent);
- appender(data, "<uuid value=\"");
+ for (; i < 32; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
- snprintf(buf, STRBUFSIZE - 1,
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- (unsigned char) value->val.uuid.value.
- uuid128.data[0],
- (unsigned char) value->val.uuid.value.
- uuid128.data[1],
- (unsigned char) value->val.uuid.value.
- uuid128.data[2],
- (unsigned char) value->val.uuid.value.
- uuid128.data[3],
- (unsigned char) value->val.uuid.value.
- uuid128.data[4],
- (unsigned char) value->val.uuid.value.
- uuid128.data[5],
- (unsigned char) value->val.uuid.value.
- uuid128.data[6],
- (unsigned char) value->val.uuid.value.
- uuid128.data[7],
- (unsigned char) value->val.uuid.value.
- uuid128.data[8],
- (unsigned char) value->val.uuid.value.
- uuid128.data[9],
- (unsigned char) value->val.uuid.value.
- uuid128.data[10],
- (unsigned char) value->val.uuid.value.
- uuid128.data[11],
- (unsigned char) value->val.uuid.value.
- uuid128.data[12],
- (unsigned char) value->val.uuid.value.
- uuid128.data[13],
- (unsigned char) value->val.uuid.value.
- uuid128.data[14],
- (unsigned char) value->val.uuid.value.
- uuid128.data[15]);
+ val.data[i >> 1] = strtoul(buf, 0, 16);
+ }
- appender(data, buf);
- appender(data, "\" />\n");
+ ret = sdp_data_alloc(dtd, &val);
break;
+ }
- case SDP_TEXT_STR8:
- case SDP_TEXT_STR16:
- case SDP_TEXT_STR32:
- {
- int num_chars_to_escape = 0;
- int length = value->unitSize - 1;
- char *strBuf = 0;
+ };
- hex = 0;
+ return ret;
+}
- for (i = 0; i < length; i++) {
- if (!isprint(value->val.str[i]) &&
- value->val.str[i] != '\0') {
- hex = 1;
- break;
- }
+static char *sdp_xml_parse_string_decode(const char *data, char encoding,
+ uint32_t *length)
+{
+ int len = strlen(data);
+ char *text;
- /* XML is evil, must do this... */
- if ((value->val.str[i] == '<') ||
- (value->val.str[i] == '>') ||
- (value->val.str[i] == '"') ||
- (value->val.str[i] == '&'))
- num_chars_to_escape++;
- }
+ if (encoding == SDP_XML_ENCODING_NORMAL) {
+ text = strdup(data);
+ *length = len;
+ } else {
+ char buf[3], *decoded;
+ int i;
- appender(data, indent);
+ decoded = malloc((len >> 1) + 1);
- appender(data, "<text ");
+ /* Ensure the string is a power of 2 */
+ len = (len >> 1) << 1;
- if (hex) {
- appender(data, "encoding=\"hex\" ");
- strBuf = malloc(sizeof(char)
- * ((value->unitSize-1) * 2 + 1));
+ buf[2] = '\0';
- /* Unit Size seems to include the size for dtd
- It is thus off by 1
- This is safe for Normal strings, but not
- hex encoded data */
- for (i = 0; i < (value->unitSize-1); i++)
- sprintf(&strBuf[i*sizeof(char)*2],
- "%02x",
- (unsigned char) value->val.str[i]);
+ for (i = 0; i < len; i += 2) {
+ buf[0] = data[i];
+ buf[1] = data[i + 1];
- strBuf[(value->unitSize-1) * 2] = '\0';
- }
- else {
- int j;
- /* escape the XML disallowed chars */
- strBuf = malloc(sizeof(char) *
- (value->unitSize + 1 + num_chars_to_escape * 4));
- for (i = 0, j = 0; i < length; i++) {
- if (value->val.str[i] == '&') {
- strBuf[j++] = '&';
- strBuf[j++] = 'a';
- strBuf[j++] = 'm';
- strBuf[j++] = 'p';
- }
- else if (value->val.str[i] == '<') {
- strBuf[j++] = '&';
- strBuf[j++] = 'l';
- strBuf[j++] = 't';
- }
- else if (value->val.str[i] == '>') {
- strBuf[j++] = '&';
- strBuf[j++] = 'g';
- strBuf[j++] = 't';
- }
- else if (value->val.str[i] == '"') {
- strBuf[j++] = '&';
- strBuf[j++] = 'q';
- strBuf[j++] = 'u';
- strBuf[j++] = 'o';
- strBuf[j++] = 't';
- }
- else if (value->val.str[i] == '\0') {
- strBuf[j++] = ' ';
- } else {
- strBuf[j++] = value->val.str[i];
- }
- }
-
- strBuf[j] = '\0';
+ decoded[i >> 1] = strtoul(buf, 0, 16);
}
- appender(data, "value=\"");
- appender(data, strBuf);
- appender(data, "\" />\n");
- free(strBuf);
- break;
+ decoded[len >> 1] = '\0';
+ text = decoded;
+ *length = len >> 1;
}
- case SDP_URL_STR8:
- case SDP_URL_STR16:
- case SDP_URL_STR32:
- {
- char *strBuf;
+ return text;
+}
- appender(data, indent);
- appender(data, "<url value=\"");
- strBuf = strndup(value->val.str, value->unitSize - 1);
- appender(data, strBuf);
- free(strBuf);
- appender(data, "\" />\n");
- break;
- }
+static sdp_data_t *sdp_xml_parse_url(const char *data)
+{
+ uint8_t dtd = SDP_URL_STR8;
+ char *url;
+ uint32_t length;
+ sdp_data_t *ret;
- case SDP_SEQ8:
- case SDP_SEQ16:
- case SDP_SEQ32:
- appender(data, indent);
- appender(data, "<sequence>\n");
+ url = sdp_xml_parse_string_decode(data,
+ SDP_XML_ENCODING_NORMAL, &length);
- convert_raw_data_to_xml(value->val.dataseq,
- indent_level + 1, data, appender);
+ if (length > UCHAR_MAX)
+ dtd = SDP_URL_STR16;
- appender(data, indent);
- appender(data, "</sequence>\n");
+ ret = sdp_data_alloc_with_length(dtd, url, length);
- break;
+ free(url);
- case SDP_ALT8:
- case SDP_ALT16:
- case SDP_ALT32:
- appender(data, indent);
+ return ret;
+}
- appender(data, "<alternate>\n");
+static sdp_data_t *sdp_xml_parse_text(const char *data, char encoding)
+{
+ uint8_t dtd = SDP_TEXT_STR8;
+ char *text;
+ uint32_t length;
+ sdp_data_t *ret;
- convert_raw_data_to_xml(value->val.dataseq,
- indent_level + 1, data, appender);
- appender(data, indent);
+ text = sdp_xml_parse_string_decode(data, encoding, &length);
- appender(data, "</alternate>\n");
+ if (length > UCHAR_MAX)
+ dtd = SDP_TEXT_STR16;
- break;
- }
+ ret = sdp_data_alloc_with_length(dtd, text, length);
- convert_raw_data_to_xml(value->next, indent_level, data, appender);
-}
+ free(text);
-struct conversion_data {
- void *data;
- void (*appender)(void *data, const char *);
-};
+ return ret;
+}
-static void convert_raw_attr_to_xml_func(void *val, void *data)
+static sdp_data_t *sdp_xml_parse_nil(const char *data)
{
- struct conversion_data *cd = data;
- sdp_data_t *value = val;
- char buf[STRBUFSIZE];
+ return sdp_data_alloc(SDP_DATA_NIL, 0);
+}
- buf[STRBUFSIZE - 1] = '\0';
- snprintf(buf, STRBUFSIZE - 1, "\t<attribute id=\"0x%04x\">\n",
- value->attrId);
- cd->appender(cd->data, buf);
+static sdp_data_t *sdp_xml_parse_datatype(const char *el,
+ struct sdp_xml_data *elem,
+ sdp_record_t *record)
+{
+ const char *data = elem->text;
- convert_raw_data_to_xml(value, 2, cd->data, cd->appender);
+ if (!strcmp(el, "boolean"))
+ return sdp_xml_parse_int(data, SDP_BOOL);
+ else if (!strcmp(el, "uint8"))
+ return sdp_xml_parse_int(data, SDP_UINT8);
+ else if (!strcmp(el, "uint16"))
+ return sdp_xml_parse_int(data, SDP_UINT16);
+ else if (!strcmp(el, "uint32"))
+ return sdp_xml_parse_int(data, SDP_UINT32);
+ else if (!strcmp(el, "uint64"))
+ return sdp_xml_parse_int(data, SDP_UINT64);
+ else if (!strcmp(el, "uint128"))
+ return sdp_xml_parse_int(data, SDP_UINT128);
+ else if (!strcmp(el, "int8"))
+ return sdp_xml_parse_int(data, SDP_INT8);
+ else if (!strcmp(el, "int16"))
+ return sdp_xml_parse_int(data, SDP_INT16);
+ else if (!strcmp(el, "int32"))
+ return sdp_xml_parse_int(data, SDP_INT32);
+ else if (!strcmp(el, "int64"))
+ return sdp_xml_parse_int(data, SDP_INT64);
+ else if (!strcmp(el, "int128"))
+ return sdp_xml_parse_int(data, SDP_INT128);
+ else if (!strcmp(el, "uuid"))
+ return sdp_xml_parse_uuid(data, record);
+ else if (!strcmp(el, "url"))
+ return sdp_xml_parse_url(data);
+ else if (!strcmp(el, "text"))
+ return sdp_xml_parse_text(data, elem->type);
+ else if (!strcmp(el, "nil"))
+ return sdp_xml_parse_nil(data);
- cd->appender(cd->data, "\t</attribute>\n");
+ return NULL;
}
-
-/*
- * Will convert the sdp record to XML. The appender and data can be used
- * to control where to output the record (e.g. file or a data buffer). The
- * appender will be called repeatedly with data and the character buffer
- * (containing parts of the generated XML) to append.
- */
-void convert_sdp_record_to_xml(sdp_record_t *rec,
- void *data, void (*appender)(void *, const char *))
+static void element_start(GMarkupParseContext *context,
+ const gchar *element_name, const gchar **attribute_names,
+ const gchar **attribute_values, gpointer user_data, GError **err)
{
- struct conversion_data cd;
+ struct context_data *ctx_data = user_data;
- cd.data = data;
- cd.appender = appender;
+ if (!strcmp(element_name, "record"))
+ return;
- if (rec && rec->attrlist) {
- appender(data, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n");
- appender(data, "<record>\n");
- sdp_list_foreach(rec->attrlist,
- convert_raw_attr_to_xml_func, &cd);
- appender(data, "</record>\n");
+ if (!strcmp(element_name, "attribute")) {
+ int i;
+ for (i = 0; attribute_names[i]; i++) {
+ if (!strcmp(attribute_names[i], "id")) {
+ ctx_data->attr_id = strtol(attribute_values[i], 0, 0);
+ break;
+ }
+ }
+ DBG("New attribute 0x%04x", ctx_data->attr_id);
+ return;
}
-}
-static sdp_data_t *sdp_xml_parse_uuid128(const char *data)
-{
- uint128_t val;
- unsigned int i, j;
+ if (ctx_data->stack_head) {
+ struct sdp_xml_data *newelem = sdp_xml_data_alloc();
+ newelem->next = ctx_data->stack_head;
+ ctx_data->stack_head = newelem;
+ } else {
+ ctx_data->stack_head = sdp_xml_data_alloc();
+ ctx_data->stack_head->next = NULL;
+ }
- char buf[3];
+ if (!strcmp(element_name, "sequence"))
+ ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
+ else if (!strcmp(element_name, "alternate"))
+ ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
+ else {
+ int i;
+ /* Parse value, name, encoding */
+ for (i = 0; attribute_names[i]; i++) {
+ if (!strcmp(attribute_names[i], "value")) {
+ int curlen = strlen(ctx_data->stack_head->text);
+ int attrlen = strlen(attribute_values[i]);
- memset(&val, 0, sizeof(val));
+ /* Ensure we're big enough */
+ while ((curlen + 1 + attrlen) > ctx_data->stack_head->size)
+ sdp_xml_data_expand(ctx_data->stack_head);
- buf[2] = '\0';
+ memcpy(ctx_data->stack_head->text + curlen,
+ attribute_values[i], attrlen);
+ ctx_data->stack_head->text[curlen + attrlen] = '\0';
+ }
- for (j = 0, i = 0; i < strlen(data);) {
- if (data[i] == '-') {
- i++;
- continue;
+ if (!strcmp(attribute_names[i], "encoding")) {
+ if (!strcmp(attribute_values[i], "hex"))
+ ctx_data->stack_head->type = 1;
+ }
+
+ if (!strcmp(attribute_names[i], "name"))
+ ctx_data->stack_head->name = strdup(attribute_values[i]);
}
- buf[0] = data[i];
- buf[1] = data[i + 1];
+ ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
+ ctx_data->stack_head, ctx_data->record);
- val.data[j++] = strtoul(buf, 0, 16);
- i += 2;
+ if (ctx_data->stack_head->data == NULL)
+ error("Can't parse element %s", element_name);
}
-
- return sdp_data_alloc(SDP_UUID128, &val);
}
-sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record)
+static void sdp_xml_data_free(struct sdp_xml_data *elem)
{
- sdp_data_t *ret;
- char *endptr;
- uint32_t val;
- uint16_t val2;
- int len;
-
- len = strlen(data);
+ if (elem->data)
+ sdp_data_free(elem->data);
- if (len == 36) {
- ret = sdp_xml_parse_uuid128(data);
- goto result;
- }
+ free(elem->name);
+ free(elem->text);
+ free(elem);
+}
- val = strtoll(data, &endptr, 16);
-
- /* Couldn't parse */
- if (*endptr != '\0')
- return NULL;
-
- if (val > USHRT_MAX) {
- ret = sdp_data_alloc(SDP_UUID32, &val);
- goto result;
- }
-
- val2 = val;
+static void element_end(GMarkupParseContext *context,
+ const gchar *element_name, gpointer user_data, GError **err)
+{
+ struct context_data *ctx_data = user_data;
+ struct sdp_xml_data *elem;
- ret = sdp_data_alloc(SDP_UUID16, &val2);
+ if (!strcmp(element_name, "record"))
+ return;
-result:
- if (record && ret)
- sdp_pattern_add_uuid(record, &ret->val.uuid);
+ if (!strcmp(element_name, "attribute")) {
+ if (ctx_data->stack_head && ctx_data->stack_head->data) {
+ int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
+ ctx_data->stack_head->data);
+ if (ret == -1)
+ DBG("Could not add attribute 0x%04x",
+ ctx_data->attr_id);
- return ret;
-}
+ ctx_data->stack_head->data = NULL;
+ sdp_xml_data_free(ctx_data->stack_head);
+ ctx_data->stack_head = NULL;
+ } else {
+ DBG("No data for attribute 0x%04x", ctx_data->attr_id);
+ }
+ return;
+ }
-sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd)
-{
- char *endptr;
- sdp_data_t *ret = NULL;
+ if (!ctx_data->stack_head || !ctx_data->stack_head->data) {
+ DBG("No data for %s", element_name);
+ return;
+ }
- switch (dtd) {
- case SDP_BOOL:
- {
- uint8_t val = 0;
+ if (!strcmp(element_name, "sequence")) {
+ ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
- if (!strcmp("true", data)) {
- val = 1;
+ if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
+ ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
+ ctx_data->stack_head->data->dtd = SDP_SEQ32;
+ } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
+ ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
+ ctx_data->stack_head->data->dtd = SDP_SEQ16;
+ } else {
+ ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
}
+ } else if (!strcmp(element_name, "alternate")) {
+ ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
- else if (!strcmp("false", data)) {
- val = 0;
- }
- else {
- return NULL;
+ if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
+ ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
+ ctx_data->stack_head->data->dtd = SDP_ALT32;
+ } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
+ ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
+ ctx_data->stack_head->data->dtd = SDP_ALT16;
+ } else {
+ ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
}
-
- ret = sdp_data_alloc(dtd, &val);
- break;
}
- case SDP_INT8:
- {
- int8_t val = strtoul(data, &endptr, 0);
+ if (ctx_data->stack_head->next && ctx_data->stack_head->data &&
+ ctx_data->stack_head->next->data) {
+ switch (ctx_data->stack_head->next->data->dtd) {
+ case SDP_SEQ8:
+ case SDP_SEQ16:
+ case SDP_SEQ32:
+ case SDP_ALT8:
+ case SDP_ALT16:
+ case SDP_ALT32:
+ ctx_data->stack_head->next->data->val.dataseq =
+ sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq,
+ ctx_data->stack_head->data);
+ ctx_data->stack_head->data = NULL;
+ break;
+ }
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ elem = ctx_data->stack_head;
+ ctx_data->stack_head = ctx_data->stack_head->next;
- ret = sdp_data_alloc(dtd, &val);
- break;
+ sdp_xml_data_free(elem);
}
+}
- case SDP_UINT8:
- {
- uint8_t val = strtoul(data, &endptr, 0);
+static GMarkupParser parser = {
+ element_start, element_end, NULL, NULL, NULL
+};
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+sdp_record_t *sdp_xml_parse_record(const char *data, int size)
+{
+ GMarkupParseContext *ctx;
+ struct context_data *ctx_data;
+ sdp_record_t *record;
- ret = sdp_data_alloc(dtd, &val);
- break;
+ ctx_data = malloc(sizeof(*ctx_data));
+ if (!ctx_data)
+ return NULL;
+
+ record = sdp_record_alloc();
+ if (!record) {
+ free(ctx_data);
+ return NULL;
}
- case SDP_INT16:
- {
- int16_t val = strtoul(data, &endptr, 0);
+ memset(ctx_data, 0, sizeof(*ctx_data));
+ ctx_data->record = record;
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);
- ret = sdp_data_alloc(dtd, &val);
- break;
+ if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
+ error("XML parsing error");
+ g_markup_parse_context_free(ctx);
+ sdp_record_free(record);
+ free(ctx_data);
+ return NULL;
}
- case SDP_UINT16:
- {
- uint16_t val = strtoul(data, &endptr, 0);
+ g_markup_parse_context_free(ctx);
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ free(ctx_data);
- ret = sdp_data_alloc(dtd, &val);
- break;
- }
+ return record;
+}
- case SDP_INT32:
- {
- int32_t val = strtoul(data, &endptr, 0);
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level,
+ void *data, void (*appender)(void *, const char *))
+{
+ int i, hex;
+ char buf[STRBUFSIZE];
+ char indent[MAXINDENT];
- ret = sdp_data_alloc(dtd, &val);
- break;
- }
+ if (!value)
+ return;
- case SDP_UINT32:
- {
- uint32_t val = strtoul(data, &endptr, 0);
+ if (indent_level >= MAXINDENT)
+ indent_level = MAXINDENT - 2;
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ for (i = 0; i < indent_level; i++)
+ indent[i] = '\t';
- ret = sdp_data_alloc(dtd, &val);
- break;
- }
+ indent[i] = '\0';
+ buf[STRBUFSIZE - 1] = '\0';
- case SDP_INT64:
- {
- int64_t val = strtoull(data, &endptr, 0);
+ switch (value->dtd) {
+ case SDP_DATA_NIL:
+ appender(data, indent);
+ appender(data, "<nil/>\n");
+ break;
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ case SDP_BOOL:
+ appender(data, indent);
+ appender(data, "<boolean value=\"");
+ appender(data, value->val.uint8 ? "true" : "false");
+ appender(data, "\" />\n");
+ break;
- ret = sdp_data_alloc(dtd, &val);
+ case SDP_UINT8:
+ appender(data, indent);
+ appender(data, "<uint8 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%02x", value->val.uint8);
+ appender(data, buf);
+ appender(data, "\" />\n");
break;
- }
- case SDP_UINT64:
- {
- uint64_t val = strtoull(data, &endptr, 0);
+ case SDP_UINT16:
+ appender(data, indent);
+ appender(data, "<uint16 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uint16);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- /* Failed to parse */
- if ((endptr != data) && (*endptr != '\0'))
- return NULL;
+ case SDP_UINT32:
+ appender(data, indent);
+ appender(data, "<uint32 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uint32);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- ret = sdp_data_alloc(dtd, &val);
+ case SDP_UINT64:
+ appender(data, indent);
+ appender(data, "<uint64 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%016jx", value->val.uint64);
+ appender(data, buf);
+ appender(data, "\" />\n");
break;
- }
- case SDP_INT128:
case SDP_UINT128:
- {
- uint128_t val;
- int i = 0;
- char buf[3];
+ appender(data, indent);
+ appender(data, "<uint128 value=\"");
- buf[2] = '\0';
+ for (i = 0; i < 16; i++) {
+ sprintf(&buf[i * 2], "%02x",
+ (unsigned char) value->val.uint128.data[i]);
+ }
- for (; i < 32; i += 2) {
- buf[0] = data[i];
- buf[1] = data[i + 1];
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- val.data[i >> 1] = strtoul(buf, 0, 16);
- }
+ case SDP_INT8:
+ appender(data, indent);
+ appender(data, "<int8 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int8);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- ret = sdp_data_alloc(dtd, &val);
+ case SDP_INT16:
+ appender(data, indent);
+ appender(data, "<int16 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int16);
+ appender(data, buf);
+ appender(data, "\" />\n");
break;
- }
- };
+ case SDP_INT32:
+ appender(data, indent);
+ appender(data, "<int32 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int32);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- return ret;
-}
+ case SDP_INT64:
+ appender(data, indent);
+ appender(data, "<int64 value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "%jd", value->val.int64);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
-static char *sdp_xml_parse_string_decode(const char *data, char encoding, uint32_t *length)
-{
- int len = strlen(data);
- char *text;
+ case SDP_INT128:
+ appender(data, indent);
+ appender(data, "<int128 value=\"");
- if (encoding == SDP_XML_ENCODING_NORMAL) {
- text = strdup(data);
- *length = len;
- } else {
- char buf[3], *decoded;
- int i;
+ for (i = 0; i < 16; i++) {
+ sprintf(&buf[i * 2], "%02x",
+ (unsigned char) value->val.int128.data[i]);
+ }
+ appender(data, buf);
- decoded = malloc((len >> 1) + 1);
+ appender(data, "\" />\n");
+ break;
- /* Ensure the string is a power of 2 */
- len = (len >> 1) << 1;
+ case SDP_UUID16:
+ appender(data, indent);
+ appender(data, "<uuid value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uuid.value.uuid16);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- buf[2] = '\0';
+ case SDP_UUID32:
+ appender(data, indent);
+ appender(data, "<uuid value=\"");
+ snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uuid.value.uuid32);
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- for (i = 0; i < len; i += 2) {
- buf[0] = data[i];
- buf[1] = data[i + 1];
+ case SDP_UUID128:
+ appender(data, indent);
+ appender(data, "<uuid value=\"");
- decoded[i >> 1] = strtoul(buf, 0, 16);
- }
+ snprintf(buf, STRBUFSIZE - 1,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[0],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[1],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[2],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[3],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[4],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[5],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[6],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[7],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[8],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[9],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[10],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[11],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[12],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[13],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[14],
+ (unsigned char) value->val.uuid.value.
+ uuid128.data[15]);
- decoded[len >> 1] = '\0';
- text = decoded;
- *length = len >> 1;
- }
+ appender(data, buf);
+ appender(data, "\" />\n");
+ break;
- return text;
-}
+ case SDP_TEXT_STR8:
+ case SDP_TEXT_STR16:
+ case SDP_TEXT_STR32:
+ {
+ int num_chars_to_escape = 0;
+ int length = value->unitSize - 1;
+ char *strBuf = 0;
-sdp_data_t *sdp_xml_parse_url(const char *data)
-{
- uint8_t dtd = SDP_URL_STR8;
- char *url;
- uint32_t length;
- sdp_data_t *ret;
+ hex = 0;
- url = sdp_xml_parse_string_decode(data,
- SDP_XML_ENCODING_NORMAL, &length);
+ for (i = 0; i < length; i++) {
+ if (!isprint(value->val.str[i]) &&
+ value->val.str[i] != '\0') {
+ hex = 1;
+ break;
+ }
- if (length > UCHAR_MAX)
- dtd = SDP_URL_STR16;
+ /* XML is evil, must do this... */
+ if ((value->val.str[i] == '<') ||
+ (value->val.str[i] == '>') ||
+ (value->val.str[i] == '"') ||
+ (value->val.str[i] == '&'))
+ num_chars_to_escape++;
+ }
- ret = sdp_data_alloc_with_length(dtd, url, length);
+ appender(data, indent);
- free(url);
+ appender(data, "<text ");
- return ret;
-}
+ if (hex) {
+ appender(data, "encoding=\"hex\" ");
+ strBuf = malloc(sizeof(char)
+ * ((value->unitSize-1) * 2 + 1));
-sdp_data_t *sdp_xml_parse_text(const char *data, char encoding)
-{
- uint8_t dtd = SDP_TEXT_STR8;
- char *text;
- uint32_t length;
- sdp_data_t *ret;
+ /* Unit Size seems to include the size for dtd
+ It is thus off by 1
+ This is safe for Normal strings, but not
+ hex encoded data */
+ for (i = 0; i < (value->unitSize-1); i++)
+ sprintf(&strBuf[i*sizeof(char)*2],
+ "%02x",
+ (unsigned char) value->val.str[i]);
- text = sdp_xml_parse_string_decode(data, encoding, &length);
+ strBuf[(value->unitSize-1) * 2] = '\0';
+ } else {
+ int j;
+ /* escape the XML disallowed chars */
+ strBuf = malloc(sizeof(char) *
+ (value->unitSize + 1 + num_chars_to_escape * 4));
+ for (i = 0, j = 0; i < length; i++) {
+ if (value->val.str[i] == '&') {
+ strBuf[j++] = '&';
+ strBuf[j++] = 'a';
+ strBuf[j++] = 'm';
+ strBuf[j++] = 'p';
+ } else if (value->val.str[i] == '<') {
+ strBuf[j++] = '&';
+ strBuf[j++] = 'l';
+ strBuf[j++] = 't';
+ } else if (value->val.str[i] == '>') {
+ strBuf[j++] = '&';
+ strBuf[j++] = 'g';
+ strBuf[j++] = 't';
+ } else if (value->val.str[i] == '"') {
+ strBuf[j++] = '&';
+ strBuf[j++] = 'q';
+ strBuf[j++] = 'u';
+ strBuf[j++] = 'o';
+ strBuf[j++] = 't';
+ } else if (value->val.str[i] == '\0') {
+ strBuf[j++] = ' ';
+ } else {
+ strBuf[j++] = value->val.str[i];
+ }
+ }
- if (length > UCHAR_MAX)
- dtd = SDP_TEXT_STR16;
+ strBuf[j] = '\0';
+ }
- ret = sdp_data_alloc_with_length(dtd, text, length);
+ appender(data, "value=\"");
+ appender(data, strBuf);
+ appender(data, "\" />\n");
+ free(strBuf);
+ break;
+ }
- free(text);
+ case SDP_URL_STR8:
+ case SDP_URL_STR16:
+ case SDP_URL_STR32:
+ {
+ char *strBuf;
- return ret;
-}
+ appender(data, indent);
+ appender(data, "<url value=\"");
+ strBuf = strndup(value->val.str, value->unitSize - 1);
+ appender(data, strBuf);
+ free(strBuf);
+ appender(data, "\" />\n");
+ break;
+ }
-sdp_data_t *sdp_xml_parse_nil(const char *data)
-{
- return sdp_data_alloc(SDP_DATA_NIL, 0);
-}
+ case SDP_SEQ8:
+ case SDP_SEQ16:
+ case SDP_SEQ32:
+ appender(data, indent);
+ appender(data, "<sequence>\n");
-#define DEFAULT_XML_DATA_SIZE 1024
+ convert_raw_data_to_xml(value->val.dataseq,
+ indent_level + 1, data, appender);
-struct sdp_xml_data *sdp_xml_data_alloc(void)
-{
- struct sdp_xml_data *elem;
+ appender(data, indent);
+ appender(data, "</sequence>\n");
- elem = malloc(sizeof(struct sdp_xml_data));
- if (!elem)
- return NULL;
+ break;
- memset(elem, 0, sizeof(struct sdp_xml_data));
+ case SDP_ALT8:
+ case SDP_ALT16:
+ case SDP_ALT32:
+ appender(data, indent);
- /* Null terminate the text */
- elem->size = DEFAULT_XML_DATA_SIZE;
- elem->text = malloc(DEFAULT_XML_DATA_SIZE);
- elem->text[0] = '\0';
+ appender(data, "<alternate>\n");
- return elem;
-}
+ convert_raw_data_to_xml(value->val.dataseq,
+ indent_level + 1, data, appender);
+ appender(data, indent);
-void sdp_xml_data_free(struct sdp_xml_data *elem)
-{
- if (elem->data)
- sdp_data_free(elem->data);
+ appender(data, "</alternate>\n");
- free(elem->name);
- free(elem->text);
- free(elem);
+ break;
+ }
+
+ convert_raw_data_to_xml(value->next, indent_level, data, appender);
}
-struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem)
-{
- char *newbuf;
+struct conversion_data {
+ void *data;
+ void (*appender)(void *data, const char *);
+};
- newbuf = malloc(elem->size * 2);
- if (!newbuf)
- return NULL;
+static void convert_raw_attr_to_xml_func(void *val, void *data)
+{
+ struct conversion_data *cd = data;
+ sdp_data_t *value = val;
+ char buf[STRBUFSIZE];
- memcpy(newbuf, elem->text, elem->size);
- elem->size *= 2;
- free(elem->text);
+ buf[STRBUFSIZE - 1] = '\0';
+ snprintf(buf, STRBUFSIZE - 1, "\t<attribute id=\"0x%04x\">\n",
+ value->attrId);
+ cd->appender(cd->data, buf);
- elem->text = newbuf;
+ convert_raw_data_to_xml(value, 2, cd->data, cd->appender);
- return elem;
+ cd->appender(cd->data, "\t</attribute>\n");
}
-sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem,
- sdp_record_t *record)
+/*
+ * Will convert the sdp record to XML. The appender and data can be used
+ * to control where to output the record (e.g. file or a data buffer). The
+ * appender will be called repeatedly with data and the character buffer
+ * (containing parts of the generated XML) to append.
+ */
+void convert_sdp_record_to_xml(sdp_record_t *rec,
+ void *data, void (*appender)(void *, const char *))
{
- const char *data = elem->text;
+ struct conversion_data cd;
- if (!strcmp(el, "boolean"))
- return sdp_xml_parse_int(data, SDP_BOOL);
- else if (!strcmp(el, "uint8"))
- return sdp_xml_parse_int(data, SDP_UINT8);
- else if (!strcmp(el, "uint16"))
- return sdp_xml_parse_int(data, SDP_UINT16);
- else if (!strcmp(el, "uint32"))
- return sdp_xml_parse_int(data, SDP_UINT32);
- else if (!strcmp(el, "uint64"))
- return sdp_xml_parse_int(data, SDP_UINT64);
- else if (!strcmp(el, "uint128"))
- return sdp_xml_parse_int(data, SDP_UINT128);
- else if (!strcmp(el, "int8"))
- return sdp_xml_parse_int(data, SDP_INT8);
- else if (!strcmp(el, "int16"))
- return sdp_xml_parse_int(data, SDP_INT16);
- else if (!strcmp(el, "int32"))
- return sdp_xml_parse_int(data, SDP_INT32);
- else if (!strcmp(el, "int64"))
- return sdp_xml_parse_int(data, SDP_INT64);
- else if (!strcmp(el, "int128"))
- return sdp_xml_parse_int(data, SDP_INT128);
- else if (!strcmp(el, "uuid"))
- return sdp_xml_parse_uuid(data, record);
- else if (!strcmp(el, "url"))
- return sdp_xml_parse_url(data);
- else if (!strcmp(el, "text"))
- return sdp_xml_parse_text(data, elem->type);
- else if (!strcmp(el, "nil"))
- return sdp_xml_parse_nil(data);
+ cd.data = data;
+ cd.appender = appender;
- return NULL;
+ if (rec && rec->attrlist) {
+ appender(data, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n");
+ appender(data, "<record>\n");
+ sdp_list_foreach(rec->attrlist,
+ convert_raw_attr_to_xml_func, &cd);
+ appender(data, "</record>\n");
+ }
}
+
diff --git a/src/sdp-xml.h b/src/sdp-xml.h
index 49efc39..d393f94 100644
--- a/src/sdp-xml.h
+++ b/src/sdp-xml.h
void convert_sdp_record_to_xml(sdp_record_t *rec,
void *user_data, void (*append_func) (void *, const char *));
-sdp_data_t *sdp_xml_parse_nil(const char *data);
-sdp_data_t *sdp_xml_parse_text(const char *data, char encoding);
-sdp_data_t *sdp_xml_parse_url(const char *data);
-sdp_data_t *sdp_xml_parse_int(const char *data, uint8_t dtd);
-sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record);
-
-struct sdp_xml_data {
- char *text; /* Pointer to the current buffer */
- int size; /* Size of the current buffer */
- sdp_data_t *data; /* The current item being built */
- struct sdp_xml_data *next; /* Next item on the stack */
- char type; /* 0 = Text or Hexadecimal */
- char *name; /* Name, optional in the dtd */
- /* TODO: What is it used for? */
-};
-
-struct sdp_xml_data *sdp_xml_data_alloc(void);
-void sdp_xml_data_free(struct sdp_xml_data *elem);
-struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem);
-
-sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem,
- sdp_record_t *record);
-
sdp_record_t *sdp_xml_parse_record(const char *data, int size);
#endif /* __SDP_XML_H */