diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2007-01-20 18:42:15 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2007-01-20 18:42:15 +0000 | 
| commit | 200bca5921ca8bd040b0644e1918e7a42e2bda96 (patch) | |
| tree | 4bf6d523694750f2d288169a9d714a7fb0565e83 | |
| parent | e21806ba296e3062960ad4f85e216d81753c5b7a (diff) | |
Update expat and GLib based parsers
| -rw-r--r-- | common/sdp-expat.c | 15 | ||||
| -rw-r--r-- | common/sdp-glib.c | 187 | 
2 files changed, 187 insertions, 15 deletions
| diff --git a/common/sdp-expat.c b/common/sdp-expat.c index 469f3a72..b591bbcc 100644 --- a/common/sdp-expat.c +++ b/common/sdp-expat.c @@ -82,7 +82,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at  		context->stack_head = newelem;  	} else {  		context->stack_head = sdp_xml_data_alloc(); -		context->stack_head->next = 0; +		context->stack_head->next = NULL;  	}  	if (!strcmp(el, "sequence")) @@ -90,7 +90,6 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at  	else if (!strcmp(el, "alternate"))  		context->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);  	else { -		const char *type = el;  		/* Parse value, name, encoding */  		for (i = 0; attr[i]; i += 2) {  			if (!strcmp(attr[i], "value")) { @@ -117,7 +116,7 @@ static void convert_xml_to_sdp_start(void *data, const char *el, const char **at  			}  		} -		context->stack_head->data = sdp_xml_parse_datatype(type, context->stack_head); +		context->stack_head->data = sdp_xml_parse_datatype(el, context->stack_head);  		/* Could not parse an entry */  		if (context->stack_head->data == NULL) @@ -140,9 +139,9 @@ static void convert_xml_to_sdp_end(void *data, const char *el)  			if (ret == -1)  				debug("Trouble adding attribute\n"); -			context->stack_head->data = 0; +			context->stack_head->data = NULL;  			sdp_xml_data_free(context->stack_head); -			context->stack_head = 0; +			context->stack_head = NULL;  		} else {  			debug("No Data for attribute: %d\n", context->attrId);  		} @@ -177,8 +176,8 @@ static void convert_xml_to_sdp_end(void *data, const char *el)  	/* If we're not inside a seq or alt, then we're inside an attribute  	   which will be taken care of later  	 */ -	if (context->stack_head->next && -		context->stack_head->data && context->stack_head->next->data) { +	if (context->stack_head->next && context->stack_head->data && +					context->stack_head->next->data) {  		switch (context->stack_head->next->data->dtd) {  		case SDP_SEQ8:  		case SDP_SEQ16: @@ -189,7 +188,7 @@ static void convert_xml_to_sdp_end(void *data, const char *el)  			context->stack_head->next->data->val.dataseq =  				sdp_seq_append(context->stack_head->next->data->val.dataseq,  								context->stack_head->data); -			context->stack_head->data = 0; +			context->stack_head->data = NULL;  			break;  		} diff --git a/common/sdp-glib.c b/common/sdp-glib.c index fa0e8a17..37c8580f 100644 --- a/common/sdp-glib.c +++ b/common/sdp-glib.c @@ -25,22 +25,176 @@  #include <config.h>  #endif +#include <stdlib.h> + +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> +  #include <glib.h>  #include "logging.h"  #include "sdp-xml.h" +static int compute_seq_size(sdp_data_t *data) +{ +	int unit_size = data->unitSize; +	sdp_data_t *seq = data->val.dataseq; + +	for (; seq; seq = seq->next) +		unit_size += seq->unitSize; + +	return unit_size; +} + +struct context_data { +	sdp_record_t *record; +	sdp_data_t attr_data; +	struct sdp_xml_data *stack_head; +	uint16_t attr_id; +}; +  static void element_start(GMarkupParseContext *context,  		const gchar *element_name, const gchar **attribute_names, -		const gchar **attribute_values, gpointer user_data, GError **error) +		const gchar **attribute_values, gpointer user_data, GError **err)  { -	debug("<%s>", element_name); +	struct context_data *ctx_data = user_data; + +	if (!strcmp(element_name, "record")) +		return; + +	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; +			} +		} +		debug("New attribute 0x%04x", ctx_data->attr_id); +		return; +	} + +	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; +	} + +	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]); + +				/* Ensure we're big enough */ +				while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) { +					sdp_xml_data_expand(ctx_data->stack_head); +				} + +				memcpy(ctx_data->stack_head->text + curlen, +						attribute_values[i], attrlen); +				ctx_data->stack_head->text[curlen + attrlen] = '\0'; +			} + +			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]); +			} +		} + +		ctx_data->stack_head->data = +			sdp_xml_parse_datatype(element_name, ctx_data->stack_head); + +		if (ctx_data->stack_head->data == NULL) +			error("Can't parse element %s", element_name); +	}  }  static void element_end(GMarkupParseContext *context, -		const gchar *element_name, gpointer user_data, GError **error) +		const gchar *element_name, gpointer user_data, GError **err)  { -	debug("</%s>", element_name); +	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) +				debug("Trouble adding attribute\n"); + +			ctx_data->stack_head->data = NULL; +			sdp_xml_data_free(ctx_data->stack_head); +			ctx_data->stack_head = NULL; +		} else { +			debug("No data for attribute 0x%04x\n", ctx_data->attr_id); +		} +		return; +	} + +	if (!strcmp(element_name, "sequence")) { +		ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); + +		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); + +		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); +		} +	} + +	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; +		} + +		elem = ctx_data->stack_head; +		ctx_data->stack_head = ctx_data->stack_head->next; + +		sdp_xml_data_free(elem); +	}  }  static GMarkupParser parser = { @@ -50,14 +204,33 @@ static GMarkupParser parser = {  sdp_record_t *sdp_xml_parse_record(const char *data, int size)  {  	GMarkupParseContext *ctx; +	struct context_data *ctx_data; +	sdp_record_t *record; + +	ctx_data = malloc(sizeof(*ctx_data)); +	if (!ctx_data) +		return NULL; + +	record = sdp_record_alloc(); +	if (!record) { +		sdp_record_free(record); +		return NULL; +	} + +	memset(ctx_data, 0, sizeof(*ctx_data)); +	ctx_data->record = record; -	ctx = g_markup_parse_context_new(&parser, 0, NULL, NULL); +	ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);  	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;  	} -	g_markup_parse_context_free(ctx); +	free(ctx_data); -	return NULL; +	return record;  } | 
