Browse Source

faux.str: faux_str_sprintf() function

Serj Kalichev 4 years ago
parent
commit
857aa097a6
3 changed files with 67 additions and 6 deletions
  1. 8 3
      faux/ini/ini.c
  2. 1 0
      faux/str.h
  3. 58 3
      faux/str/str.c

+ 8 - 3
faux/ini/ini.c

@@ -451,10 +451,15 @@ int faux_ini_write_file(const faux_ini_t *ini, const char *fn) {
 		quote_value = faux_str_chars(value, spaces) ? "\"" : "";
 
 		// Prepare INI line
-		faux_str_vcat(&line,
-			quote_name, name, quote_name, "=",
-			quote_value, value, quote_value, "\n", NULL);
+		line = faux_str_sprintf("%s%s%s=%s%s%s\n",
+			quote_name, name, quote_name,
+			quote_value, value, quote_value);
+		if (!line) {
+			faux_file_close(f);
+			return -1;
+		}
 
+		// Write to file
 		bytes_written = faux_file_write(f, line, strlen(line));
 		faux_str_free(line);
 		if (bytes_written < 0) { // Can't write to file

+ 1 - 0
faux/str.h

@@ -24,6 +24,7 @@ char *faux_str_dup(const char *str);
 char *faux_str_catn(char **str, const char *text, size_t n);
 char *faux_str_cat(char **str, const char *text);
 char *faux_str_vcat(char **str, ...);
+char *faux_str_sprintf(const char *fmt, ...);
 
 char *faux_str_tolower(const char *str);
 char *faux_str_toupper(const char *str);

+ 58 - 3
faux/str/str.c

@@ -196,12 +196,16 @@ char *faux_str_cat(char **str, const char *text) {
 	return faux_str_catn(str, text, len);
 }
 
-/** @brief Add some text to existent string.
+/** @brief Add multiply text strings to existent string.
  *
- * Concatenate two strings. Add second string to the end of the first one.
+ * Concatenate multiply strings. Add next string to the end of the previous one.
  * The first argument is address of string pointer. The pointer can be
  * changed due to realloc() features. The first pointer can be NULL. In this
  * case the memory will be malloc()-ed and stored to the first pointer.
+ * The last argument must be 'NULL'. It marks the last argument within
+ * variable arguments list.
+ *
+ * @warning If last argument is not 'NULL' then behaviour is undefined.
  *
  * @param [in,out] str Address of first string pointer.
  * @param [in] text Text to add to the first string.
@@ -211,7 +215,7 @@ char *faux_str_vcat(char **str, ...) {
 
 	va_list ap;
 	const char *arg = NULL;
-	char *retval = NULL;
+	char *retval = *str;
 
 	va_start(ap, str);
 	while ((arg = va_arg(ap, const char *))) {
@@ -223,6 +227,57 @@ char *faux_str_vcat(char **str, ...) {
 }
 
 
+/** @brief Allocates memory and sprintf() to it.
+ *
+ * Function tries to find out necessary amount of memory for specified format
+ * string and arguments. Format is same as for sprintf() function. Then
+ * function allocates memory for resulting string and sprintf() to it. So
+ * user doesn't need to allocate buffer himself. Function returns allocated
+ * string that need to be freed by faux_str_free() function later.
+ *
+ * @warning The returned pointer must be free by faux_str_free().
+ *
+ * @param [in] fmt Format string like the sprintf()'s fmt.
+ * @param [in] arg Number of arguments.
+ * @return Allocated resulting string or NULL on error.
+ */
+char *faux_str_sprintf(const char *fmt, ...) {
+
+	int size = 1;
+	char calc_buf[1] = "";
+	char *line = NULL;
+	va_list ap;
+
+	// Calculate buffer size
+	va_start(ap, fmt);
+	size = vsnprintf(calc_buf, size, fmt, ap);
+	va_end(ap);
+	// The snprintf() prior to 2.0.6 glibc version returns -1 if string
+	// was truncated. The later glibc returns required buffer size.
+	// The calc_buf can be NULL and size can be 0 for recent glibc but
+	// probably some exotic implementations can break on it. So use
+	// minimal buffer with length = 1.
+	if (size < 0)
+		return NULL;
+
+	size++; // Additional byte for '\0'
+	line = faux_zmalloc(size);
+	if (!line) // Memory problems
+		return NULL;
+
+	// Format real string
+	va_start(ap, fmt);
+	size = vsnprintf(line, size, fmt, ap);
+	va_end(ap);
+	if (size < 0) { // Some problems
+		faux_str_free(line);
+		return NULL;
+	}
+
+	return line;
+}
+
+
 /** @brief Service function to compare to chars in right way.
  *
  * The problem is char type can be signed or unsigned on different