diff mbox series

[v2,3/5] parser: Replace properties array with a group of properties

Message ID 1516199646-5607-3-git-send-email-stefan@herbrechtsmeier.net
State Accepted
Headers show
Series [v2,1/5] dict: Rename dictionary struct and its key to distinguish it from simple lists | expand

Commit Message

Stefan Herbrechtsmeier Jan. 17, 2018, 2:34 p.m. UTC
From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

---

Changes in v3:
- Suppress build warning if libconfig or libjson are disabled
- Suppress build warning if both libconfig and libjson are disabled
- Update the documentation of the SWU forwarder
- Add an array to the documentation example of SWU forwarder

Changes in v2:
- Check name and value inside add_properties_cb function to skip NULL values
- Add support for properties with value arrays

 corelib/parsing_library.c           | 16 ++++++++++++++++
 corelib/parsing_library_libconfig.c | 24 ++++++++++++++++++++++++
 corelib/parsing_library_libjson.c   | 31 +++++++++++++++++++++++++++++++
 doc/source/handlers.rst             | 12 +++++-------
 include/parselib.h                  |  9 +++++++++
 parser/parser.c                     | 35 +++++++++++++++--------------------
 6 files changed, 100 insertions(+), 27 deletions(-)

Comments

Stefano Babic Jan. 17, 2018, 6:17 p.m. UTC | #1
On 17/01/2018 15:34, stefan@herbrechtsmeier.net wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> ---
> 
> Changes in v3:
> - Suppress build warning if libconfig or libjson are disabled
> - Suppress build warning if both libconfig and libjson are disabled
> - Update the documentation of the SWU forwarder
> - Add an array to the documentation example of SWU forwarder
> 
> Changes in v2:
> - Check name and value inside add_properties_cb function to skip NULL values
> - Add support for properties with value arrays
> 
>  corelib/parsing_library.c           | 16 ++++++++++++++++
>  corelib/parsing_library_libconfig.c | 24 ++++++++++++++++++++++++
>  corelib/parsing_library_libjson.c   | 31 +++++++++++++++++++++++++++++++
>  doc/source/handlers.rst             | 12 +++++-------
>  include/parselib.h                  |  9 +++++++++
>  parser/parser.c                     | 35 +++++++++++++++--------------------
>  6 files changed, 100 insertions(+), 27 deletions(-)
> 
> diff --git a/corelib/parsing_library.c b/corelib/parsing_library.c
> index 5d30f2d..767d30d 100644
> --- a/corelib/parsing_library.c
> +++ b/corelib/parsing_library.c
> @@ -62,6 +62,22 @@ void *get_child(parsertype p, void *e, const char *name)
>  	return NULL;
>  }
>  
> +void iterate_field(parsertype p, void *e, iterate_callback cb, void *data)
> +{
> +	switch (p) {
> +	case LIBCFG_PARSER:
> +		iterate_field_libconfig(e, cb, data);
> +		break;
> +	case JSON_PARSER:
> +		iterate_field_json(e, cb, data);
> +		break;
> +	default:
> +		(void)e;
> +		(void)cb;
> +		(void)data;
> +	}
> +}
> +
>  void *get_elem_from_idx(parsertype p, void *node, int idx)
>  {
>  	switch (p) {
> diff --git a/corelib/parsing_library_libconfig.c b/corelib/parsing_library_libconfig.c
> index 0664712..415116b 100644
> --- a/corelib/parsing_library_libconfig.c
> +++ b/corelib/parsing_library_libconfig.c
> @@ -47,6 +47,30 @@ void *get_child_libconfig(void *e, const char *name)
>  	return config_setting_get_member(e, name);
>  }
>  
> +void iterate_field_libconfig(config_setting_t *e, iterate_callback cb, void *data)
> +{
> +	config_setting_t *entry, *elem;
> +	const char *str;
> +	int i, j;
> +
> +	if (!cb)
> +		return;
> +
> +	for (i = 0; i < config_setting_length(e); i++) {
> +		entry = config_setting_get_elem(e, i);
> +		if (!config_setting_length(entry)) {
> +			str = config_setting_get_string(entry);
> +			cb(entry->name, str, data);
> +		} else {
> +			for (j = 0; j < config_setting_length(entry); j++) {
> +				elem = config_setting_get_elem(entry, j);
> +				str = config_setting_get_string(elem);
> +				cb(entry->name, str, data);
> +			}
> +		}
> +	}
> +}
> +
>  void get_field_cfg(config_setting_t *e, const char *path, void *dest)
>  {
>  	config_setting_t *elem;
> diff --git a/corelib/parsing_library_libjson.c b/corelib/parsing_library_libjson.c
> index 844aca9..e24d1e9 100644
> --- a/corelib/parsing_library_libjson.c
> +++ b/corelib/parsing_library_libjson.c
> @@ -51,6 +51,37 @@ void *get_child_json(json_object *e, const char *path)
>  	return node;
>  }
>  
> +void iterate_field_json(json_object *e, iterate_callback cb, void *data)
> +{
> +	json_object *subnode;
> +	const char *str;
> +	int i;
> +
> +	if (!cb || json_object_get_type(e) != json_type_object)
> +		return;
> +
> +	json_object_object_foreach(e, key, node) {
> +		switch (json_object_get_type(node)) {
> +		case json_type_string:
> +			str = json_object_get_string(node);
> +			cb(key, str, data);
> +			break;
> +		case json_type_array:
> +			for (i = 0; i < json_object_array_length(node); i++) {
> +				subnode = json_object_array_get_idx(node, i);
> +				if (json_object_get_type(subnode) != json_type_string)
> +					continue;
> +
> +				str = json_object_get_string(subnode);
> +				cb(key, str, data);
> +			}
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +}
> +
>  const char *get_field_string_json(json_object *e, const char *path)
>  {
>  	const char *str;
> diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
> index 74bf94a..a27647f 100644
> --- a/doc/source/handlers.rst
> +++ b/doc/source/handlers.rst
> @@ -321,8 +321,8 @@ is connected to the network and the "slaves" are hidden to the external world.
>  The master is then the only interface to the world. A general SWU can contain
>  embedded SWU images as single artifacts, and the SWU handler will forward it
>  to the devices listed in the description of the artifact.
> -The handler can have a list of "url" properties. Each url is the address of a
> -secondary board where SWUpdate is running with webserver activated.
> +The handler can have a single "url" properties entry with an array of urls. Each url
> +is the address of a secondary board where SWUpdate is running with webserver activated.
>  The SWU handler expects to talk with SWUpdate's embedded webserver. This helps
>  to update systems where an old version of SWUpdate is running, because the
>  embedded webserver is a common feature present in all versions.
> @@ -340,9 +340,7 @@ the SWU forwarder:
>  			filename = "image.swu";
>  			type = "swuforward";
>  
> -			properties: (
> -			{
> -				name = "url";
> -				value = "http://192.168.178.41:8080";
> -			});
> +			properties: {
> +				url = ["http://192.168.178.41:8080", "http://192.168.178.42:8080"];
> +			};
>  		});
> diff --git a/include/parselib.h b/include/parselib.h
> index e189751..f53dd00 100644
> --- a/include/parselib.h
> +++ b/include/parselib.h
> @@ -15,6 +15,9 @@ typedef enum {
>  	JSON_PARSER
>  } parsertype;
>  
> +typedef void (*iterate_callback)(const char *name, const char *value,
> +				 void *data);
> +
>  #ifdef CONFIG_LIBCONFIG
>  #include <libconfig.h>
>  #define LIBCONFIG_VERSION ((LIBCONFIG_VER_MAJOR << 16) | \
> @@ -26,6 +29,8 @@ typedef enum {
>  void get_value_libconfig(const config_setting_t *e, void *dest);
>  void get_field_cfg(config_setting_t *e, const char *path, void *dest);
>  void *get_child_libconfig(void *e, const char *name);
> +void iterate_field_libconfig(config_setting_t *e, iterate_callback cb,
> +			     void *data);
>  const char *get_field_string_libconfig(config_setting_t *e, const char *path);
>  
>  #else
> @@ -35,6 +40,7 @@ const char *get_field_string_libconfig(config_setting_t *e, const char *path);
>  #define find_node_libconfig(cfg, field, swcfg) (NULL)
>  #define get_field_string_libconfig(e, path)	(NULL)
>  #define get_child_libconfig(e, name)		(NULL)
> +#define iterate_field_libconfig(e, cb, data)	{ }
>  #define get_field_cfg(e, path, dest)
>  #endif
>  
> @@ -45,6 +51,7 @@ const char *get_field_string_json(json_object *e, const char *path);
>  void get_value_json(json_object *e, void *dest);
>  void get_field_json(json_object *e, const char *path, void *dest);
>  void *get_child_json(json_object *e, const char *name);
> +void iterate_field_json(json_object *e, iterate_callback cb, void *data);
>  json_object *find_json_recursive_node(json_object *root, const char **names);
>  json_object *json_get_key(json_object *json_root, const char *key);
>  const char *json_get_value(struct json_object *json_root,
> @@ -56,6 +63,7 @@ char *json_get_data_url(json_object *json_root, const char *key);
>  #define find_node_json(a, b, c)		(NULL)
>  #define get_field_string_json(e, path)  (NULL)
>  #define get_child_json(e, name)		(NULL)
> +#define iterate_field_json(e, cb, data)	{ }
>  #define get_field_json(e, path, dest)
>  #define json_object_object_get_ex(a,b,c) (0)
>  #define json_object_array_get_idx(a, b)	(0)
> @@ -70,6 +78,7 @@ void get_field_string_with_size(parsertype p, void *e, const char *path,
>  int get_array_length(parsertype p, void *root);
>  void *get_elem_from_idx(parsertype p, void *node, int idx);
>  void *get_child(parsertype p, void *node, const char *name);
> +void iterate_field(parsertype p, void *e, iterate_callback cb, void *data);
>  void get_field(parsertype p, void *e, const char *path, void *dest);
>  int exist_field_string(parsertype p, void *e, const char *path);
>  void get_hash_value(parsertype p, void *elem, unsigned char *hash);
> diff --git a/parser/parser.c b/parser/parser.c
> index 2e9208d..f07559d 100644
> --- a/parser/parser.c
> +++ b/parser/parser.c
> @@ -140,32 +140,27 @@ static void *find_node(parsertype p, void *root, const char *node,
>  	return NULL;
>  }
>  
> -static void add_properties(parsertype p, void *node, struct img_type *image)
> +static void add_properties_cb(const char *name, const char *value, void *data)
>  {
> +	struct img_type *image = (struct img_type *)data;
>  
> -	void *properties, *prop;
> -	int count, i;
> +	if (!name || !value)
> +		return;
> +
> +	TRACE("\t\tProperty %s: %s", name, value);
> +	if (dict_insert_value(&image->properties, (char *)name, (char *)value))
> +		ERROR("Property not stored, skipping...");
> +}
> +
> +static void add_properties(parsertype p, void *node, struct img_type *image)
> +{
> +	void *properties;
>  
>  	properties = get_child(p, node, "properties");
>  	if (properties) {
> -		count = get_array_length(p, properties);
> -
> -		TRACE("Found %d properties for %s:", count, image->fname);
> -
> -		for (i = 0; i < count; i++) {
> -			char key[255];
> -			char value[255];
> -			prop = get_elem_from_idx(p, properties, i);
> -			GET_FIELD_STRING(p, prop, "name", key);
> -			GET_FIELD_STRING(p, prop, "value", value);
> -			TRACE("\t\tProperty %d: name=%s val=%s ", i,
> -				key,
> -				value
> -			);
> -			if (dict_insert_value(&image->properties, key, value))
> -				ERROR("Property not stored, skipping...");
> +		TRACE("Found properties for %s:", image->fname);
>  
> -		}
> +		iterate_field(p, properties, add_properties_cb, image);
>  	}
>  }
>  
> 

Reviewed-by: Stefano Babic <sbabic@denx.de>
Tested-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic
Stefano Babic Jan. 19, 2018, 9:34 a.m. UTC | #2
On 17/01/2018 15:34, stefan@herbrechtsmeier.net wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> ---
> 

Applied to -master, thanks !

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/corelib/parsing_library.c b/corelib/parsing_library.c
index 5d30f2d..767d30d 100644
--- a/corelib/parsing_library.c
+++ b/corelib/parsing_library.c
@@ -62,6 +62,22 @@  void *get_child(parsertype p, void *e, const char *name)
 	return NULL;
 }
 
+void iterate_field(parsertype p, void *e, iterate_callback cb, void *data)
+{
+	switch (p) {
+	case LIBCFG_PARSER:
+		iterate_field_libconfig(e, cb, data);
+		break;
+	case JSON_PARSER:
+		iterate_field_json(e, cb, data);
+		break;
+	default:
+		(void)e;
+		(void)cb;
+		(void)data;
+	}
+}
+
 void *get_elem_from_idx(parsertype p, void *node, int idx)
 {
 	switch (p) {
diff --git a/corelib/parsing_library_libconfig.c b/corelib/parsing_library_libconfig.c
index 0664712..415116b 100644
--- a/corelib/parsing_library_libconfig.c
+++ b/corelib/parsing_library_libconfig.c
@@ -47,6 +47,30 @@  void *get_child_libconfig(void *e, const char *name)
 	return config_setting_get_member(e, name);
 }
 
+void iterate_field_libconfig(config_setting_t *e, iterate_callback cb, void *data)
+{
+	config_setting_t *entry, *elem;
+	const char *str;
+	int i, j;
+
+	if (!cb)
+		return;
+
+	for (i = 0; i < config_setting_length(e); i++) {
+		entry = config_setting_get_elem(e, i);
+		if (!config_setting_length(entry)) {
+			str = config_setting_get_string(entry);
+			cb(entry->name, str, data);
+		} else {
+			for (j = 0; j < config_setting_length(entry); j++) {
+				elem = config_setting_get_elem(entry, j);
+				str = config_setting_get_string(elem);
+				cb(entry->name, str, data);
+			}
+		}
+	}
+}
+
 void get_field_cfg(config_setting_t *e, const char *path, void *dest)
 {
 	config_setting_t *elem;
diff --git a/corelib/parsing_library_libjson.c b/corelib/parsing_library_libjson.c
index 844aca9..e24d1e9 100644
--- a/corelib/parsing_library_libjson.c
+++ b/corelib/parsing_library_libjson.c
@@ -51,6 +51,37 @@  void *get_child_json(json_object *e, const char *path)
 	return node;
 }
 
+void iterate_field_json(json_object *e, iterate_callback cb, void *data)
+{
+	json_object *subnode;
+	const char *str;
+	int i;
+
+	if (!cb || json_object_get_type(e) != json_type_object)
+		return;
+
+	json_object_object_foreach(e, key, node) {
+		switch (json_object_get_type(node)) {
+		case json_type_string:
+			str = json_object_get_string(node);
+			cb(key, str, data);
+			break;
+		case json_type_array:
+			for (i = 0; i < json_object_array_length(node); i++) {
+				subnode = json_object_array_get_idx(node, i);
+				if (json_object_get_type(subnode) != json_type_string)
+					continue;
+
+				str = json_object_get_string(subnode);
+				cb(key, str, data);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 const char *get_field_string_json(json_object *e, const char *path)
 {
 	const char *str;
diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 74bf94a..a27647f 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -321,8 +321,8 @@  is connected to the network and the "slaves" are hidden to the external world.
 The master is then the only interface to the world. A general SWU can contain
 embedded SWU images as single artifacts, and the SWU handler will forward it
 to the devices listed in the description of the artifact.
-The handler can have a list of "url" properties. Each url is the address of a
-secondary board where SWUpdate is running with webserver activated.
+The handler can have a single "url" properties entry with an array of urls. Each url
+is the address of a secondary board where SWUpdate is running with webserver activated.
 The SWU handler expects to talk with SWUpdate's embedded webserver. This helps
 to update systems where an old version of SWUpdate is running, because the
 embedded webserver is a common feature present in all versions.
@@ -340,9 +340,7 @@  the SWU forwarder:
 			filename = "image.swu";
 			type = "swuforward";
 
-			properties: (
-			{
-				name = "url";
-				value = "http://192.168.178.41:8080";
-			});
+			properties: {
+				url = ["http://192.168.178.41:8080", "http://192.168.178.42:8080"];
+			};
 		});
diff --git a/include/parselib.h b/include/parselib.h
index e189751..f53dd00 100644
--- a/include/parselib.h
+++ b/include/parselib.h
@@ -15,6 +15,9 @@  typedef enum {
 	JSON_PARSER
 } parsertype;
 
+typedef void (*iterate_callback)(const char *name, const char *value,
+				 void *data);
+
 #ifdef CONFIG_LIBCONFIG
 #include <libconfig.h>
 #define LIBCONFIG_VERSION ((LIBCONFIG_VER_MAJOR << 16) | \
@@ -26,6 +29,8 @@  typedef enum {
 void get_value_libconfig(const config_setting_t *e, void *dest);
 void get_field_cfg(config_setting_t *e, const char *path, void *dest);
 void *get_child_libconfig(void *e, const char *name);
+void iterate_field_libconfig(config_setting_t *e, iterate_callback cb,
+			     void *data);
 const char *get_field_string_libconfig(config_setting_t *e, const char *path);
 
 #else
@@ -35,6 +40,7 @@  const char *get_field_string_libconfig(config_setting_t *e, const char *path);
 #define find_node_libconfig(cfg, field, swcfg) (NULL)
 #define get_field_string_libconfig(e, path)	(NULL)
 #define get_child_libconfig(e, name)		(NULL)
+#define iterate_field_libconfig(e, cb, data)	{ }
 #define get_field_cfg(e, path, dest)
 #endif
 
@@ -45,6 +51,7 @@  const char *get_field_string_json(json_object *e, const char *path);
 void get_value_json(json_object *e, void *dest);
 void get_field_json(json_object *e, const char *path, void *dest);
 void *get_child_json(json_object *e, const char *name);
+void iterate_field_json(json_object *e, iterate_callback cb, void *data);
 json_object *find_json_recursive_node(json_object *root, const char **names);
 json_object *json_get_key(json_object *json_root, const char *key);
 const char *json_get_value(struct json_object *json_root,
@@ -56,6 +63,7 @@  char *json_get_data_url(json_object *json_root, const char *key);
 #define find_node_json(a, b, c)		(NULL)
 #define get_field_string_json(e, path)  (NULL)
 #define get_child_json(e, name)		(NULL)
+#define iterate_field_json(e, cb, data)	{ }
 #define get_field_json(e, path, dest)
 #define json_object_object_get_ex(a,b,c) (0)
 #define json_object_array_get_idx(a, b)	(0)
@@ -70,6 +78,7 @@  void get_field_string_with_size(parsertype p, void *e, const char *path,
 int get_array_length(parsertype p, void *root);
 void *get_elem_from_idx(parsertype p, void *node, int idx);
 void *get_child(parsertype p, void *node, const char *name);
+void iterate_field(parsertype p, void *e, iterate_callback cb, void *data);
 void get_field(parsertype p, void *e, const char *path, void *dest);
 int exist_field_string(parsertype p, void *e, const char *path);
 void get_hash_value(parsertype p, void *elem, unsigned char *hash);
diff --git a/parser/parser.c b/parser/parser.c
index 2e9208d..f07559d 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -140,32 +140,27 @@  static void *find_node(parsertype p, void *root, const char *node,
 	return NULL;
 }
 
-static void add_properties(parsertype p, void *node, struct img_type *image)
+static void add_properties_cb(const char *name, const char *value, void *data)
 {
+	struct img_type *image = (struct img_type *)data;
 
-	void *properties, *prop;
-	int count, i;
+	if (!name || !value)
+		return;
+
+	TRACE("\t\tProperty %s: %s", name, value);
+	if (dict_insert_value(&image->properties, (char *)name, (char *)value))
+		ERROR("Property not stored, skipping...");
+}
+
+static void add_properties(parsertype p, void *node, struct img_type *image)
+{
+	void *properties;
 
 	properties = get_child(p, node, "properties");
 	if (properties) {
-		count = get_array_length(p, properties);
-
-		TRACE("Found %d properties for %s:", count, image->fname);
-
-		for (i = 0; i < count; i++) {
-			char key[255];
-			char value[255];
-			prop = get_elem_from_idx(p, properties, i);
-			GET_FIELD_STRING(p, prop, "name", key);
-			GET_FIELD_STRING(p, prop, "value", value);
-			TRACE("\t\tProperty %d: name=%s val=%s ", i,
-				key,
-				value
-			);
-			if (dict_insert_value(&image->properties, key, value))
-				ERROR("Property not stored, skipping...");
+		TRACE("Found properties for %s:", image->fname);
 
-		}
+		iterate_field(p, properties, add_properties_cb, image);
 	}
 }