commit 63966f207ec9bd8c5b55845e94da9df2750dd653
parent 97f3cef9ce0a984aa3d724c5650ec37b50b56018
Author: Morel Bérenger <berengermorel76@gmail.com>
Date:   Wed, 12 Aug 2020 20:41:16 +0200
add esc_fputs function
Diffstat:
2 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/btl/src/utils.cpp b/btl/src/utils.cpp
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <iterator>
+#include <algorithm>
+#include "utils.hpp"
+
+//would probably be better without that many ifs
+int esc_fputs( const char *s, FILE *stream )
+{
+	assert( s && stream && "nullpointer provided to esc_fputs" );
+	if( !( s && stream ) )
+	{
+		errno = EINVAL;
+		return EOF;
+	}
+
+	const char *str_end = s + strlen( s );
+	const char *chunk_start = s;
+	const char *chunk_end;
+	char bslash[2] = { '\\', '\\' };
+	char tohex [4] = { '\\', 'x', 0, 0 };
+	char ch;
+	char const* buf;
+	size_t sz;
+
+	do
+	{
+		chunk_end = std::find_if( chunk_start, str_end, []( const char c ){ return c < 0x20 || c == '\\'; } );
+		assert( chunk_end - chunk_start >= 0 );
+		if( !fwrite( chunk_start, static_cast<size_t>( chunk_end - chunk_start ), 1, stream ) )
+		{
+			return INT_MAX;
+		}
+		if( chunk_end != str_end )
+		{
+			ch = *chunk_end;
+			buf = bslash;
+			sz = sizeof( bslash );
+			if( ch != '\\' )
+			{
+				buf = tohex;
+				sz = sizeof( tohex );
+				//quick'n dirty ascii to hex convertion for values < 0x20 (space)
+				tohex[2] = '0' + ( ch >> 4 );
+				ch &= 0x0F;
+				tohex[3] = ch + '0' + ( ch > 9 ? 'A' - ( '9' + 1 ) : 0 );
+			}
+			if( !fwrite( buf, sz, 1, stream ) )
+			{
+				return INT_MAX;
+			}
+		}
+		chunk_start = chunk_end;
+	} while( chunk_start != str_end );
+	return 0;
+}
diff --git a/btl/src/utils.hpp b/btl/src/utils.hpp
@@ -41,4 +41,8 @@ inline bool empty_array( T* arr )
 	return arr && *arr == INVALID;
 }
 
+//like fputs, but when character is blank, prints the C escape instead
+//returns 0 on success, INT_MAX on error
+int esc_fputs( const char *s, FILE *stream );
+
 #endif