Browse Source

faux: str: faux_str_c_esc()

Serj Kalichev 4 years ago
parent
commit
bcac7307cd
1 changed files with 89 additions and 6 deletions
  1. 89 6
      faux/str/str.c

+ 89 - 6
faux/str/str.c

@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <stdio.h>
 
 #include "faux/ctype.h"
 #include "faux/str.h"
@@ -91,8 +92,8 @@ char *faux_str_dupn(const char *str, size_t n) {
  * @param [in] str String to convert.
  * @return Pointer to lowercase string copy or NULL.
  */
-char *faux_str_tolower(const char *str)
-{
+char *faux_str_tolower(const char *str) {
+
 	char *res = faux_str_dup(str);
 	char *p = res;
 
@@ -117,8 +118,8 @@ char *faux_str_tolower(const char *str)
  * @param [in] str String to convert.
  * @return Pointer to lowercase string copy or NULL.
  */
-char *faux_str_toupper(const char *str)
-{
+char *faux_str_toupper(const char *str) {
+
 	char *res = faux_str_dup(str);
 	char *p = res;
 
@@ -290,8 +291,8 @@ int faux_str_casecmp(const char *str1, const char *str2) {
  * Pointer to first occurence of substring in the string.
  * NULL on error
  */
-char *faux_str_casestr(const char *haystack, const char *needle)
-{
+char *faux_str_casestr(const char *haystack, const char *needle) {
+
 	const char *ptr = haystack;
 	size_t ptr_len = 0;
 	size_t needle_len = 0;
@@ -315,6 +316,88 @@ char *faux_str_casestr(const char *haystack, const char *needle)
 	return NULL; // Not found
 }
 
+
+/** Prepare string for embedding to C-code (make escaping).
+ *
+ * @warning The returned pointer must be freed by faux_str_free().
+ * @param [in] src String for escaping.
+ * @return Escaped string or NULL on error.
+ */
+char *faux_str_c_esc(const char *src) {
+
+	const char *src_ptr = src;
+	char *dst = NULL;
+	char *dst_ptr = NULL;
+	char *escaped = NULL;
+	size_t src_len = 0;
+	size_t dst_len = 0;
+
+	assert(src);
+	if (!src)
+		return NULL;
+
+	src_len = strlen(src);
+	// Calculate max destination string size.
+	// The worst case is when each src character will be replaced by
+	// something like '\xff'. So it's 4 dst chars for 1 src one.
+	dst_len = (src_len * 4) + 1; // one byte for '\0'
+	dst = faux_zmalloc(dst_len);
+	assert(dst);
+	if (!dst)
+		return NULL;
+
+	while (*src_ptr != '\0') {
+		char *esc = NULL; // escaped replacement
+		char buf[5]; // longest 'char' (4 bytes) + '\0'
+		size_t len = 0;
+
+		switch (*src_ptr) {
+		case '\n':
+			esc = "\\n";
+			break;
+		case '\"':
+			esc = "\\\"";
+			break;
+		case '\\':
+			esc = "\\\\";
+			break;
+		case '\'':
+			esc = "\\\'";
+			break;
+		case '\r':
+			esc = "\\r";
+			break;
+		case '\t':
+			esc = "\\t";
+			break;
+		default:
+			// Check is the symbol control character. Control
+			// characters has codes from 0x00 to 0x1f.
+			if (((unsigned char)*src_ptr & 0xe0) == 0) { // control
+				snprintf(buf, sizeof(buf), "\\x%02x",
+					(unsigned char)*src_ptr);
+				buf[4] = '\0'; // for safety
+			} else {
+				buf[0] = *src_ptr; // Common character
+				buf[1] = '\0';
+			}
+			esc = buf;
+			break;
+		}
+
+		len = strlen(esc);
+		memcpy(dst_ptr, esc, len); // zmalloc() nullify the rest
+		dst_ptr += len;
+		src_ptr++;
+	}
+
+	escaped = faux_str_dup(dst); // Free some memory
+	faux_str_free(dst); // 'dst' size >= 'escaped' size
+
+	return escaped;
+}
+
+
 /* TODO: If it nedeed?
 const char *faux_str_nextword(const char *string,
 	size_t *len, size_t *offset, size_t *quoted)