DPDK patches and discussions
 help / color / mirror / Atom feed
From: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v2 4/6] cfgfile: added line continue character '\' to make multiline values possible
Date: Wed, 17 Jun 2015 16:48:46 +0200	[thread overview]
Message-ID: <1434552528-3576-5-git-send-email-maciejx.t.gajdzica@intel.com> (raw)
In-Reply-To: <1434552528-3576-1-git-send-email-maciejx.t.gajdzica@intel.com>

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

Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@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

  parent reply	other threads:[~2015-06-17 15:08 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-17 14:48 [dpdk-dev] [PATCH v2 0/6] cfgfile: config file parsing extension Maciej Gajdzica
2015-06-17 14:48 ` [dpdk-dev] [PATCH v2 1/6] librte_cfgfile: fix code formating in header file Maciej Gajdzica
2015-06-17 14:48 ` [dpdk-dev] [PATCH v2 2/6] librte_compat: fix macro definition Maciej Gajdzica
2015-06-17 14:48 ` [dpdk-dev] [PATCH v2 3/6] cfgfile: split rte_cfgfile_load to smaller functions Maciej Gajdzica
2015-06-17 14:48 ` Maciej Gajdzica [this message]
2015-06-17 14:48 ` [dpdk-dev] [PATCH v2 5/6] cfgfile: fixed calling free for each section in rte_cfgfile_close Maciej Gajdzica
2015-06-18 12:29   ` Thomas Monjalon
2015-06-18 13:08     ` Gajdzica, MaciejX T
2015-06-17 14:48 ` [dpdk-dev] [PATCH v2 6/6] cfgfile: added new implementation of section parsing Maciej Gajdzica
2015-06-18 12:37   ` Thomas Monjalon
2015-06-18 13:09     ` Gajdzica, MaciejX T
2015-06-17 16:51 ` [dpdk-dev] [PATCH v2 0/6] cfgfile: config file parsing extension Dumitrescu, Cristian
2015-06-18 12:44 ` Thomas Monjalon
2015-06-22 14:58 ` Gajdzica, MaciejX T

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1434552528-3576-5-git-send-email-maciejx.t.gajdzica@intel.com \
    --to=maciejx.t.gajdzica@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).