Browse Source

faux: ini: Update faux_ini_parse_str()

Serj Kalichev 4 years ago
parent
commit
3f0f81ed10
3 changed files with 130 additions and 70 deletions
  1. 70 18
      faux/ini/ini.c
  2. 1 1
      faux/str.h
  3. 59 51
      faux/str/str.c

+ 70 - 18
faux/ini/ini.c

@@ -214,6 +214,57 @@ const faux_pair_t *faux_ini_each(faux_ini_node_t **iter) {
 }
 
 
+static char *faux_ini_purify_word(const char *str)
+{
+	const char *word;
+	const char *string = str;
+	bool_t quoted = BOOL_FALSE;
+	size_t len = 0;
+
+	assert(str);
+	if (!str)
+		return NULL;
+
+	// Find the start of a word
+	while (*string != '\0' && isspace(*string)) {
+		string++;
+	}
+	// Is this the start of a quoted string?
+	if ('"' == *string) {
+		quoted = BOOL_TRUE;
+		string++;
+	}
+	word = string; // Begin of purified word
+
+	// Find the end of the word
+	while (*string != '\0') {
+		if ('\\' == *string) {
+			string++;
+			if ('\0' == *string) // Unfinished escaping
+				break; // Don't increment 'len'
+			len++;
+			// Skip escaped char
+			string++;
+			len++;
+			continue;
+		}
+		// End of word
+		if (!quoted && isspace(*string))
+			break;
+		if ('"' == *string) {
+			// End of a quoted string
+			break;
+		}
+		string++;
+		len++;
+	}
+
+	if (len == 0)
+		return NULL;
+
+	return faux_str_dupn(word, len);
+}
+
 /** @brief Parse string for pairs 'name/value'.
  *
  * String can contain an `name/value` pairs in following format:
@@ -242,44 +293,45 @@ int faux_ini_parse_str(faux_ini_t *ini, const char *string) {
 
 	buffer = faux_str_dup(string);
 	// Now loop though each line
-	for (line = strtok_r(buffer, "\n", &saveptr);
-		line; line = strtok_r(NULL, "\n", &saveptr)) {
+	for (line = strtok_r(buffer, "\n\r", &saveptr);
+		line; line = strtok_r(NULL, "\n\r", &saveptr)) {
 
+		// Now 'line' contain one 'name/value' pair. Single line.
 		char *str = NULL;
 		char *name = NULL;
 		char *value = NULL;
 		char *savestr = NULL;
-		char *ns = line;
-		const char *begin = NULL;
-		size_t len = 0;
-		size_t offset = 0;
-		size_t quoted = 0;
 		char *rname = NULL;
 		char *rvalue = NULL;
 
-		if (!*ns) // Empty
+		while ((*line != '\0') && isspace(*line)) // Skip spaces
+			line++;
+		if ('\0' == *line) // Empty line
 			continue;
-		while (*ns && isspace(*ns))
-			ns++;
-		if ('#' == *ns) // Comment
+		if ('#' == *line) // Comment. Skip it.
 			continue;
-		if ('=' == *ns) // Broken string
-			continue;
-		str = faux_str_dup(ns);
+		str = faux_str_dup(line);
+
+		// Find out name
 		name = strtok_r(str, "=", &savestr);
 		if (!name) {
 			faux_str_free(str);
 			continue;
 		}
+		rname = faux_ini_purify_word(name);
+		if (!rname) {
+			faux_str_free(str);
+			continue;
+		}
+
+		// Find out value
 		value = strtok_r(NULL, "=", &savestr);
-		begin = faux_str_nextword(name, &len, &offset, &quoted);
-		rname = faux_str_dupn(begin, len);
 		if (!value) { // Empty value
 			rvalue = NULL;
 		} else {
-			begin = faux_str_nextword(value, &len, &offset, &quoted);
-			rvalue = faux_str_dupn(begin, len);
+			rvalue = faux_ini_purify_word(value);
 		}
+
 		faux_ini_set(ini, rname, rvalue);
 		faux_str_free(rname);
 		faux_str_free(rvalue);

+ 1 - 1
faux/str.h

@@ -27,7 +27,7 @@ char *faux_str_cat(char **str, const char *text);
 char *faux_str_tolower(const char *str);
 char *faux_str_toupper(const char *str);
 
-int faux_str_ncasecmp(const char *str1, const char *str2, size_t n);
+int faux_str_casecmpn(const char *str1, const char *str2, size_t n);
 int faux_str_casecmp(const char *str1, const char *str2);
 char *faux_str_casestr(const char *haystack, const char *needle);
 

+ 59 - 51
faux/str/str.c

@@ -227,7 +227,7 @@ static int faux_str_cmp_chars(char char1, char char2) {
  * @param [in] n Number of characters to compare.
  * @return < 0, 0, > 0, see the strcasecmp().
  */
-int faux_str_ncasecmp(const char *str1, const char *str2, size_t n) {
+int faux_str_casecmpn(const char *str1, const char *str2, size_t n) {
 
 	const char *p1 = str1;
 	const char *p2 = str2;
@@ -280,6 +280,16 @@ int faux_str_casecmp(const char *str1, const char *str2) {
 }
 
 
+/** @brief Finds the first occurrence of the substring in the string
+ *
+ * Function is a faux version of strcasestr() function.
+ *
+ * @param [in] haystack String to find substring in it.
+ * @param [in] needle Substring to find.
+ * @return
+ * Pointer to first occurence of substring in the string.
+ * NULL on error
+ */
 char *faux_str_casestr(const char *haystack, const char *needle)
 {
 	const char *ptr = haystack;
@@ -295,7 +305,7 @@ char *faux_str_casestr(const char *haystack, const char *needle)
 	needle_len = strlen(needle);
 
 	while ((*ptr != '\0') && (ptr_len >= needle_len)) {
-		int res = faux_str_ncasecmp(ptr, needle, needle_len);
+		int res = faux_str_casecmpn(ptr, needle, needle_len);
 		if (0 == res)
 			return (char *)ptr;
 		ptr++;
@@ -305,6 +315,53 @@ char *faux_str_casestr(const char *haystack, const char *needle)
 	return NULL; // Not found
 }
 
+/* TODO: If it nedeed?
+const char *faux_str_nextword(const char *string,
+	size_t *len, size_t *offset, size_t *quoted)
+{
+	const char *word;
+
+	*quoted = 0;
+
+	// Find the start of a word (not including an opening quote)
+	while (*string && isspace(*string)) {
+		string++;
+		(*offset)++;
+	}
+	// Is this the start of a quoted string ?
+	if (*string == '"') {
+		*quoted = 1;
+		string++;
+	}
+	word = string;
+	*len = 0;
+
+	// Find the end of the word
+	while (*string) {
+		if (*string == '\\') {
+			string++;
+			(*len)++;
+			if (*string) {
+				(*len)++;
+				string++;
+			}
+			continue;
+		}
+		// End of word
+		if (!*quoted && isspace(*string))
+			break;
+		if (*string == '"') {
+			// End of a quoted string
+			*quoted = 2;
+			break;
+		}
+		(*len)++;
+		string++;
+	}
+
+	return word;
+}
+*/
 
 // TODO: Is it needed?
 /*
@@ -441,55 +498,6 @@ const char *lub_string_suffix(const char *string)
 }
 */
 
-// TODO: Is it needed?
-/*--------------------------------------------------------- */
-/*
-const char *lub_string_nextword(const char *string,
-	size_t *len, size_t *offset, size_t *quoted)
-{
-	const char *word;
-
-	*quoted = 0;
-
-	// Find the start of a word (not including an opening quote)
-	while (*string && isspace(*string)) {
-		string++;
-		(*offset)++;
-	}
-	// Is this the start of a quoted string ?
-	if (*string == '"') {
-		*quoted = 1;
-		string++;
-	}
-	word = string;
-	*len = 0;
-
-	// Find the end of the word
-	while (*string) {
-		if (*string == '\\') {
-			string++;
-			(*len)++;
-			if (*string) {
-				(*len)++;
-				string++;
-			}
-			continue;
-		}
-		// End of word
-		if (!*quoted && isspace(*string))
-			break;
-		if (*string == '"') {
-			// End of a quoted string
-			*quoted = 2;
-			break;
-		}
-		(*len)++;
-		string++;
-	}
-
-	return word;
-}
-*/
 
 // TODO: Is it needed?
 /*--------------------------------------------------------- */