[dpdk-dev] [PATCH v2 4/6] cfgfile: added line continue character '\' to make multiline values possible

Maciej Gajdzica maciejx.t.gajdzica at intel.com
Wed Jun 17 16:48:46 CEST 2015


From: Pawel Wodkowski <pawelx.wodkowski at intel.com>

Signed-off-by: Pawel Wodkowski <pawelx.wodkowski at intel.com>
---
 lib/librte_cfgfile/rte_cfgfile.c |  147 ++++++++++++++++++++++++++++++++++----
 1 file changed, 133 insertions(+), 14 deletions(-)

diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c
index 2e78583..4e77ef5 100644
--- a/lib/librte_cfgfile/rte_cfgfile.c
+++ b/lib/librte_cfgfile/rte_cfgfile.c
@@ -116,6 +116,122 @@ strip_comment(char *buffer, size_t len)
 	return len;
 }
 
+/* Get line from file. It concatanate lines with line continue.
+ * If *line is not NULL it must point to malloced data buffer and *len must
+ * be the length of *line.
+ */
+static int
+rte_cfgfile_getline(char **line, size_t *len, FILE *f, size_t *lineno)
+{
+	char *str = NULL;
+	size_t str_len = 0;
+
+	void *buf;
+	char *line_str = NULL;
+	size_t line_size = 0; /* Whole buffer size */
+	ssize_t line_len = 0; /* Length of line_str */
+
+	size_t line_cnt = 0;
+	int status = 0;
+
+	if (!line) {
+		status = EINVAL;
+		goto error_exit;
+	}
+
+	while (1) {
+		line_len = getline(&line_str, &line_size, f);
+		if (line_len <= 0) {
+			if (!feof(f)) {
+				status = -EIO;
+				goto error_exit;
+			}
+
+			break;
+		}
+
+		line_cnt++;
+		/* Replace last CR with LF */
+		if (line_len > 0 && line_str[line_len - 1] == '\r')
+			line_str[line_len - 1] = '\n';
+
+		/* Replace last CRLF with LF */
+		if (line_len > 1 && line_str[line_len - 2] == '\r' &&
+					line_str[line_len - 1] == '\n') {
+			line_str[line_len - 1] = '\0';
+			line_str[line_len - 2] = '\n';
+			line_len -= 1;
+		}
+
+		line_len = strip_comment(line_str, line_len);
+
+		/* Special case for first line. */
+		if (str == NULL) {
+			if (line_len == 0)
+				continue;
+
+			str = line_str;
+			str_len = line_len;
+
+			line_str = NULL;
+			line_len = 0;
+		} else {
+			if (line_len == 0)
+				break;
+
+			buf = realloc(str, str_len + line_len + 1);
+			if (buf == NULL) {
+				status = -ENOMEM;
+				goto error_exit;
+			}
+
+			str = buf;
+			memcpy(&str[str_len], line_str, line_len + 1);
+
+			str_len += line_len;
+		}
+
+		/* Check for line continue */
+		if (str_len < 2 || str[str_len - 1] != '\n' || str[str_len - 2] != '\\')
+			break;
+
+		/* Remove line continue character. */
+		str[str_len - 1] = '\0';
+		/* Change new line into space */
+		str[str_len - 2] = ' ';
+		str_len -= 1;
+	}
+
+	if (str_len) {
+		/* Squeeze str */
+		buf = realloc(str, str_len + 1);
+		if (buf == NULL) {
+			status = -ENOMEM;
+			goto error_exit;
+		}
+
+		free(*line);
+		*line = buf;
+	}
+
+	if (len)
+		*len = str_len;
+
+	if (lineno)
+		*lineno += line_cnt;
+
+	free(line_str);
+	return 0;
+
+error_exit:
+	printf("Error: %s\n", strerror(status));
+	if (lineno)
+		*lineno += line_cnt;
+	free(str);
+	free(line_str);
+	return status;
+}
+
 /**
  * Create new apty config file object.
  *
@@ -153,9 +269,11 @@ rte_cfgfile_read(FILE *f, int flags)
 	int allocated_entries = 0;
 	int curr_section = -1;
 	int curr_entry = -1;
-	char buffer[256];
-	int lineno = 0;
+	char *buffer = NULL;
+	size_t len;
+	size_t lineno = 0;
 	struct rte_cfgfile *cfg = NULL;
+	int status;
 
 	if (f == NULL)
 		return NULL;
@@ -164,15 +282,12 @@ rte_cfgfile_read(FILE *f, int flags)
 	if (cfg == NULL)
 		goto error2;
 
-	while (fgets(buffer, sizeof(buffer), f) != NULL) {
-		size_t len = strnlen(buffer, sizeof(buffer));
-		lineno++;
-		if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) {
-			printf("Error line %d - no \\n found on string. "
-					"Check if line too long\n", lineno);
-			goto error1;
-		}
-		len = strip_comment(buffer, len);
+	while (!feof(f)) {
+		status = rte_cfgfile_getline(&buffer, &len, f, &lineno);
+		if (status)
+			break;
+		else if (!len)
+			continue;
 
 		len = _strip(buffer, len);
 		if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL)
@@ -182,7 +297,7 @@ rte_cfgfile_read(FILE *f, int flags)
 			/* section heading line */
 			char *end = memchr(buffer, ']', len);
 			if (end == NULL) {
-				printf("Error line %d - no terminating '['"
+				printf("Error line %zu - no terminating '['"
 					"character found\n", lineno);
 				goto error1;
 			}
@@ -227,7 +342,7 @@ rte_cfgfile_read(FILE *f, int flags)
 		} else {
 			/* value line */
 			if (curr_section < 0) {
-				printf("Error line %d - value outside of"
+				printf("Error line %zu - value outside of"
 					"section\n", lineno);
 				goto error1;
 			}
@@ -237,7 +352,7 @@ rte_cfgfile_read(FILE *f, int flags)
 			char *split[2];
 			if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=')
 				!= 2) {
-				printf("Error at line %d - cannot split "
+				printf("Error at line %zu - cannot split "
 					"string\n", lineno);
 				goto error1;
 			}
@@ -275,6 +390,10 @@ rte_cfgfile_read(FILE *f, int flags)
 				sizeof(entry->value)));
 		}
 	}
+
+	if (status)
+		goto error1;
+
 	fclose(f);
 	cfg->flags = flags;
 	cfg->num_sections = curr_section + 1;
-- 
1.7.9.5



More information about the dev mailing list