commit: e347dbeed068198522c58c9ea5785477e17be282
parent 5e0d5c0545d8de4b3a177a09a7e0e4038f33910e
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat, 24 Aug 2024 06:45:58 +0200
cmd/cut: support -d ''
Diffstat:
3 files changed, 46 insertions(+), 16 deletions(-)
diff --git a/cmd/cut.1 b/cmd/cut.1
@@ -49,8 +49,9 @@ Cut codepoints based on
 .Ar list .
 .It Fl d Ar delim
 Set the field delimiter to the character
-.Ar delim .
-(default: \t)
+.Ar delim ,
+if an empty string is passed, then NULL is used as separator.
+(default:\ \et)
 .It Fl f Ar list
 Cut fields based on
 .Ar list .
diff --git a/cmd/cut.c b/cmd/cut.c
@@ -286,13 +286,23 @@ cut_f(FILE *in, const char *filename)
 
 		if(line[nread - 1] == '\n') line[--nread] = '\0';
 
-		if(opt_s && strchr(line, delim) == NULL) continue;
+		if(opt_s)
+		{
+			size_t i = 0;
+			for(; i < (size_t)nread; i++)
+				if(line[i] == delim) break;
+
+			if(i == (size_t)nread) continue;
+		}
 
 		bool need_sep = false;
-		size_t i = 0;
-		char *toks = NULL;
-		for(char *c = strtok_r(line, &delim, &toks); c != NULL; c = strtok_r(NULL, &delim, &toks), i++)
+		char *c = line;
+		for(size_t pos = 0, i = 0; pos <= (size_t)nread; pos++)
 		{
+			if(pos < (size_t)nread && line[pos] != delim) continue;
+
+			line[pos] = '\0';
+
 			if(i >= list_len)
 			{
 				if(!nostop) break;
@@ -301,16 +311,17 @@ cut_f(FILE *in, const char *filename)
 
 				fputs(c, stdout);
 				need_sep = true;
-				continue;
 			}
-
-			if(list[i])
+			else if(list[i])
 			{
 				if(need_sep) fputc(delim, stdout);
 
 				fputs(c, stdout);
 				need_sep = true;
 			}
+
+			i++;
+			c = line + pos + 1;
 		}
 
 		fputc('\n', stdout);
@@ -386,12 +397,7 @@ main(int argc, char *argv[])
 			opt_list = optarg;
 			break;
 		case 'd':
-			if(optarg[0] == '\0')
-			{
-				fprintf(stderr, "cut: Option '-d' requires a character, got an empty string\n");
-				return 1;
-			}
-			if(optarg[1] != '\0')
+			if(optarg[0] != '\0' && optarg[1] != '\0')
 			{
 				fprintf(stderr, "cut: Option '-d' only accepts single characters, got \"%s\"\n", optarg);
 				return 1;
diff --git a/test-cmd/cut.sh b/test-cmd/cut.sh
@@ -4,10 +4,27 @@
 
 WD="$(dirname "$0")/../"
 target="${WD}/cmd/cut"
-plans=12
+plans=15
 . "${WD}/test-cmd/tap.sh"
 . "${WD}/test-cmd/init_env.sh"
 
+t_null_f2()
+{
+	name="null_f2"
+	exp="_2"
+
+	count=$((count+1))
+	out="$("$target" -d '' -f2 "${WD}/test-cmd/inputs/strings/length" 2>&1)"
+	ret="$?"
+	if [ "$?" != 0 ]; then
+		printf 'not ok %s - %s\n' "$count $name" "$out"
+	elif [ "$out" != "$exp" ]; then
+		printf 'not ok %s - (%s != %s)\n' "$count $name" "$out" "$exp"
+	else
+		printf 'ok %s\n' "$count $name"
+	fi
+}
+
 t 'bytes:2-3,10-20,4,12' "-b 2-3,10-20,4,12 ${WD}/test-cmd/inputs/alnum" '1239ABCDEFGHIJ
 '
 t 'bytes:11-' "-b 11- ${WD}/test-cmd/inputs/alnum" 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
@@ -49,3 +66,9 @@ t --input="$fields" f-2 '-f-2' '1	2
 
 a	b
 '
+
+t --input="hello" 'hello_f1' '-f1' 'hello
+'
+t --input="hello" 'hello_f1_s' '-f1 -s'
+
+t_null_f2