hal/hald device_info.c,1.19,1.20

David Zeuthen david at freedesktop.org
Thu Feb 3 14:09:49 PST 2005


Update of /cvs/hal/hal/hald
In directory gabe:/tmp/cvs-serv17509/hald

Modified Files:
	device_info.c 
Log Message:
2005-02-03  David Zeuthen  <davidz at redhat.com>

	* hald/device_info.c (handle_match): Handle contains and
	contains_ncase for strlist properties. Also allow <merge key="foo"
	type="strlist> blah</merge> to create a new strlist; possibly
	destroy an existing strlist with the single elem 'blah'.
	(handle_append_prepend): Renamed from handle_append since it also
	covers prepend now and supports strlist's.
	(handle_remove): New function to cover <remove key="foobar"
	type="strlist">blah</remove> (removes element 'blah' from strlist
	'foobar') and <remove key="foobar"/> to completely remove a
	property.
	(start): Support <prepend> on both strings and strlists. Support
	<remove>
	(end): Support the new directives.

	Here is an example of the new directives; I'm pasting it here
	so it's handy when the spec needs to be updated. Oh, and for
	when I get around to adding test cases for this :-)

	<append key="bat0" type="string">foo0</append>
	<merge key="baz0" type="strlist">foz0</merge>
	<append key="bar0" type="strlist">foo0</append>
	<append key="bar0" type="strlist">foo1</append>
	<append key="bar0" type="strlist">foo2</append>
	<append key="bar0" type="strlist">foo3</append>

	<prepend key="dat0" type="string">foo0</prepend>
	<merge key="daz0" type="strlist">foz0</merge>
	<prepend key="dar0" type="strlist">foo0</prepend>
	<prepend key="dar0" type="strlist">foo1</prepend>
	<prepend key="dar0" type="strlist">foo2</prepend>
	<prepend key="dar0" type="strlist">foo3</prepend>

	<remove key="t1" type="strlist">val1</remove>
	<remove key="t2"/>
	<remove key="t3"/>



Index: device_info.c
===================================================================
RCS file: /cvs/hal/hal/hald/device_info.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- device_info.c	31 Jan 2005 20:06:39 -0000	1.19
+++ device_info.c	3 Feb 2005 22:09:47 -0000	1.20
@@ -78,6 +78,12 @@
 
 	/** Processing an append element */
 	CURELEM_APPEND = 4,
+
+	/** Processing an prepend element */
+	CURELEM_PREPEND = 5,
+
+	/** Processing an prepend element */
+	CURELEM_REMOVE = 6
 };
 
 /** What and how to merge */
@@ -88,7 +94,9 @@
 	MERGE_TYPE_INT32,
 	MERGE_TYPE_UINT64,
 	MERGE_TYPE_DOUBLE,
-	MERGE_TYPE_COPY_PROPERTY
+	MERGE_TYPE_COPY_PROPERTY,
+	MERGE_TYPE_STRLIST,
+	MERGE_TYPE_REMOVE
 };
 
 /** Parsing Context
@@ -538,18 +546,33 @@
 
 		needle = attr[3];
 
-		if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
-			return FALSE;
-
-		if (hal_device_has_property (d, prop_to_check)) {
-			const char *haystack;
-
-			haystack = hal_device_property_get_string (d, prop_to_check);
-			if (needle != NULL && haystack != NULL && strstr (haystack, needle)) {
-				contains = TRUE;
+		if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
+			if (hal_device_has_property (d, prop_to_check)) {
+				const char *haystack;
+				
+				haystack = hal_device_property_get_string (d, prop_to_check);
+				if (needle != NULL && haystack != NULL && strstr (haystack, needle)) {
+					contains = TRUE;
+				}
+				
 			}
+		} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && 
+			   needle != NULL) {
+			GSList *i;
+			GSList *value;
 
+			value = hal_device_property_get_strlist (d, prop_to_check);
+			for (i = value; i != NULL; i = g_slist_next (i)) {
+				const char *str = i->data;
+				if (strcmp (str, needle) == 0) {
+					contains = TRUE;
+					break;
+				}
+			}
+		} else {
+			return FALSE;
 		}
+
 		return contains;
 	} else if (strcmp (attr[2], "contains_ncase") == 0) {
 		const char *needle;
@@ -557,22 +580,37 @@
 
 		needle = attr[3];
 
-		if (hal_device_property_get_type (d, prop_to_check) != HAL_PROPERTY_TYPE_STRING)
-			return FALSE;
-
-		if (hal_device_has_property (d, prop_to_check)) {
-			char *needle_lowercase;
-			char *haystack_lowercase;
-
-			needle_lowercase   = g_utf8_strdown (needle, -1);
-			haystack_lowercase = g_utf8_strdown (hal_device_property_get_string (d, prop_to_check), -1);
-			if (needle_lowercase != NULL && haystack_lowercase != NULL && strstr (haystack_lowercase, needle_lowercase)) {
-				contains_ncase = TRUE;
+		if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRING) {
+			if (hal_device_has_property (d, prop_to_check)) {
+				char *needle_lowercase;
+				char *haystack_lowercase;
+				
+				needle_lowercase   = g_utf8_strdown (needle, -1);
+				haystack_lowercase = g_utf8_strdown (hal_device_property_get_string (d, prop_to_check), -1);
+				if (needle_lowercase != NULL && haystack_lowercase != NULL && strstr (haystack_lowercase, needle_lowercase)) {
+					contains_ncase = TRUE;
+				}
+				
+				g_free (needle_lowercase);
+				g_free (haystack_lowercase);
 			}
+		} else if (hal_device_property_get_type (d, prop_to_check) == HAL_PROPERTY_TYPE_STRLIST && 
+			   needle != NULL) {
+			GSList *i;
+			GSList *value;
 
-			g_free (needle_lowercase);
-			g_free (haystack_lowercase);
+			value = hal_device_property_get_strlist (d, prop_to_check);
+			for (i = value; i != NULL; i = g_slist_next (i)) {
+				const char *str = i->data;
+				if (g_ascii_strcasecmp (str, needle) == 0) {
+					contains_ncase = TRUE;
+					break;
+				}
+			}
+		} else {
+			return FALSE;
 		}
+
 		return contains_ncase;
 	} else if (strcmp (attr[2], "compare_lt") == 0) {
 		dbus_int64_t result;
@@ -652,6 +690,10 @@
 		/* match string property */
 		pc->merge_type = MERGE_TYPE_DOUBLE;
 		return;
+	} else if (strcmp (attr[3], "strlist") == 0) {
+		/* match string property */
+		pc->merge_type = MERGE_TYPE_STRLIST;
+		return;
 	} else if (strcmp (attr[3], "copy_property") == 0) {
 		/* copy another property */
 		pc->merge_type = MERGE_TYPE_COPY_PROPERTY;
@@ -661,13 +703,13 @@
 	return;
 }
 
-/** Called when the append element begins.
+/** Called when the append or prepend element begins.
  *
  *  @param  pc                  Parsing context
  *  @param  attr                Attribute key/value pairs
  */
 static void
-handle_append (ParsingContext * pc, const char **attr)
+handle_append_prepend (ParsingContext * pc, const char **attr)
 {
 	int num_attrib;
 
@@ -688,9 +730,13 @@
 		return;
 
 	if (strcmp (attr[3], "string") == 0) {
-		/* match string property */
+		/* append to a string */
 		pc->merge_type = MERGE_TYPE_STRING;
 		return;
+	} else if (strcmp (attr[3], "strlist") == 0) {
+		/* append to a string list*/
+		pc->merge_type = MERGE_TYPE_STRLIST;
+		return;
 	} else if (strcmp (attr[3], "copy_property") == 0) {
 		/* copy another property */
 		pc->merge_type = MERGE_TYPE_COPY_PROPERTY;
@@ -700,6 +746,48 @@
 	return;
 }
 
+/** Called when the append or prepend element begins.
+ *
+ *  @param  pc                  Parsing context
+ *  @param  attr                Attribute key/value pairs
+ */
+static void
+handle_remove (ParsingContext * pc, const char **attr)
+{
+	int num_attrib;
+
+	pc->merge_type = MERGE_TYPE_UNKNOWN;
+
+	for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
+		;
+	}
+
+	if (num_attrib != 2 && num_attrib != 4)
+		return;
+
+	if (strcmp (attr[0], "key") != 0)
+		return;
+	strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
+
+	if (num_attrib == 4) {
+		if (strcmp (attr[2], "type") != 0)
+			return;
+
+		if (strcmp (attr[3], "strlist") == 0) {
+			/* remove from strlist */
+			pc->merge_type = MERGE_TYPE_STRLIST;
+			return;
+		} else {
+			pc->merge_type = MERGE_TYPE_UNKNOWN;
+			return;
+		}
+	} else {
+		pc->merge_type = MERGE_TYPE_REMOVE;
+	}
+
+	return;
+}
+
 /** Abort parsing of document
  *
  *  @param  pc                  Parsing context
@@ -790,7 +878,41 @@
 
 		pc->curelem = CURELEM_APPEND;
 		if (pc->match_ok) {
-			handle_append (pc, attr);
+			handle_append_prepend (pc, attr);
+		} else {
+			/*HAL_INFO(("No merge!")); */
+		}
+	} else if (strcmp (el, "prepend") == 0) {
+		if (pc->curelem != CURELEM_DEVICE
+		    && pc->curelem != CURELEM_MATCH) {
+			HAL_ERROR (("%s:%d:%d: Element <prepend> can only be "
+				    "inside <device> and <match>", 
+				    pc->file, 
+				    XML_GetCurrentLineNumber (pc->parser), 
+				    XML_GetCurrentColumnNumber (pc->parser)));
+			parsing_abort (pc);
+		}
+
+		pc->curelem = CURELEM_PREPEND;
+		if (pc->match_ok) {
+			handle_append_prepend (pc, attr);
+		} else {
+			/*HAL_INFO(("No merge!")); */
+		}
+	} else if (strcmp (el, "remove") == 0) {
+		if (pc->curelem != CURELEM_DEVICE
+		    && pc->curelem != CURELEM_MATCH) {
+			HAL_ERROR (("%s:%d:%d: Element <remove> can only be "
+				    "inside <device> and <match>", 
+				    pc->file, 
+				    XML_GetCurrentLineNumber (pc->parser), 
+				    XML_GetCurrentColumnNumber (pc->parser)));
+			parsing_abort (pc);
+		}
+
+		pc->curelem = CURELEM_REMOVE;
+		if (pc->match_ok) {
+			handle_remove (pc, attr);
 		} else {
 			/*HAL_INFO(("No merge!")); */
 		}
@@ -853,10 +975,18 @@
 
 		switch (pc->merge_type) {
 		case MERGE_TYPE_STRING:
-			hal_device_property_set_string (pc->device, pc->merge_key,
-						pc->cdata_buf);
+			hal_device_property_set_string (pc->device, pc->merge_key, pc->cdata_buf);
 			break;
 
+		case MERGE_TYPE_STRLIST:
+		{
+			int type = hal_device_property_get_type (pc->device, pc->merge_key);
+			if (type == HAL_PROPERTY_TYPE_STRLIST || type == HAL_PROPERTY_TYPE_NIL) {
+				hal_device_property_remove (pc->device, pc->merge_key);
+				hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
+			}
+			break;
+		}
 
 		case MERGE_TYPE_INT32:
 			{
@@ -933,34 +1063,96 @@
 			break;
 		}
 	} else if (pc->curelem == CURELEM_APPEND && pc->match_ok && 
-		   hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING) {
+		   (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
+		    hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
+		    hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_NIL)) {
 		char buf[256];
 		char buf2[256];
 
 		/* As soon as we are appending, we have matched the device... */
 		pc->device_matched = TRUE;
 
-		switch (pc->merge_type) {
-		case MERGE_TYPE_STRING:
-			strncpy (buf, pc->cdata_buf, sizeof (buf));
-			break;
+		if (pc->merge_type == MERGE_TYPE_STRLIST) {
+			hal_device_property_strlist_append (pc->device, pc->merge_key, pc->cdata_buf);
+		} else {
+			const char *existing_string;
+			
+			switch (pc->merge_type) {
+			case MERGE_TYPE_STRING:
+				strncpy (buf, pc->cdata_buf, sizeof (buf));
+				break;
+				
+			case MERGE_TYPE_COPY_PROPERTY:
+				hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
+				break;
+				
+			default:
+				HAL_ERROR (("Unknown merge_type=%d='%c'", pc->merge_type, pc->merge_type));
+				break;
+			}
+			
+			existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
+			if (existing_string != NULL) {
+				strncpy (buf2, existing_string, sizeof (buf2));
+				strncat (buf2, buf, sizeof (buf2) - strlen(buf2));
+			} else {
+				strncpy (buf2, buf, sizeof (buf2));
+			}
+			hal_device_property_set_string (pc->device, pc->merge_key, buf2);
+		}
+	} else if (pc->curelem == CURELEM_PREPEND && pc->match_ok && 
+		   (hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRING ||
+		    hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_STRLIST ||
+		    hal_device_property_get_type (pc->device, pc->merge_key) == HAL_PROPERTY_TYPE_NIL)) {
+		char buf[256];
+		char buf2[256];
 
-		case MERGE_TYPE_COPY_PROPERTY:
-			hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
-			break;
+		/* As soon as we are prepending, we have matched the device... */
+		pc->device_matched = TRUE;
 
-		default:
-			HAL_ERROR (("Unknown merge_type=%d='%c'",
-				    pc->merge_type, pc->merge_type));
-			break;
+		if (pc->merge_type == MERGE_TYPE_STRLIST) {
+			hal_device_property_strlist_prepend (pc->device, pc->merge_key, pc->cdata_buf);
+		} else {
+			const char *existing_string;
+			
+			switch (pc->merge_type) {
+			case MERGE_TYPE_STRING:
+				strncpy (buf, pc->cdata_buf, sizeof (buf));
+				break;
+				
+			case MERGE_TYPE_COPY_PROPERTY:
+				hal_device_property_get_as_string (pc->device, pc->cdata_buf, buf, sizeof (buf));
+				break;
+				
+			default:
+				HAL_ERROR (("Unknown merge_type=%d='%c'", pc->merge_type, pc->merge_type));
+				break;
+			}
+			
+			existing_string = hal_device_property_get_string (pc->device, pc->merge_key);
+			if (existing_string != NULL) {
+				strncpy (buf2, buf, sizeof (buf2));
+				strncat (buf2, existing_string, sizeof (buf2) - strlen(buf2));
+			} else {
+				strncpy (buf2, buf, sizeof (buf2));
+			}
+			hal_device_property_set_string (pc->device, pc->merge_key, buf2);
 		}
+	} else if (pc->curelem == CURELEM_REMOVE && pc->match_ok) {
 
-		strncpy (buf2, hal_device_property_get_string (pc->device, pc->merge_key), sizeof (buf2));
-		strncat (buf2, buf, sizeof (buf2) - strlen(buf2));
-		hal_device_property_set_string (pc->device, pc->merge_key, buf2);
+		if (pc->merge_type == MERGE_TYPE_STRLIST) {
+			/* covers <remove key="foobar" type="strlist">blah</remove> */
+			hal_device_property_strlist_remove (pc->device, pc->merge_key, pc->cdata_buf);
+		} else {
+			/* only allow <remove key="foobar"/>, not <remove key="foobar">blah</remove> */
+			if (strlen (pc->cdata_buf) == 0) {
+				hal_device_property_remove (pc->device, pc->merge_key);
+			}
+		}
 	}
 
 
+
 	pc->cdata_buf_len = 0;
 	pc->depth--;
 




More information about the hal-commit mailing list