summary refs log tree commit diff stats
path: root/specials/file-replace.c
diff options
context:
space:
mode:
authorsmlckz <smlckz@college>2021-12-22 14:56:13 +0530
committersmlckz <smlckz@college>2021-12-22 14:56:13 +0530
commitb73983c3717642ca10e7cfe93d97609adc377da9 (patch)
treea6e9fe4c27e3caa215f8aefa9265fb52f6de4375 /specials/file-replace.c
downloadcollege-b73983c3717642ca10e7cfe93d97609adc377da9.tar.gz
backup
Diffstat (limited to 'specials/file-replace.c')
-rw-r--r--specials/file-replace.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/specials/file-replace.c b/specials/file-replace.c
new file mode 100644
index 0000000..2e01367
--- /dev/null
+++ b/specials/file-replace.c
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* for ftruncate */
+#include <unistd.h>
+#include <sys/types.h>
+
+size_t str_length(char *s)
+{
+	size_t n = 0;
+	while (*s++ != '\0') {
+		n++;
+	}
+	return n;
+}
+
+int str_equal(char *a, char *b)
+{
+	do {
+		if (*a++ != *b++) {
+			return 0;
+		}
+	} while (*b != '\0');
+	return 1;
+}
+
+long find_in_file(FILE *f, char *needle)
+{
+	size_t nlen = str_length(needle);
+	long pos = 0;
+	char *str = malloc(nlen + 1);
+	while (!feof(f) || !ferror(f)) {
+		if (fread(str, 1, nlen, f) != nlen) {
+			break;
+		}
+		str[nlen] = '\0';
+		//printf("%ld: %s\n", ftell(f), str);
+		if (str_equal(str, needle)) {
+			return pos;
+		}
+		fseek(f, ++pos, SEEK_SET);
+	}
+	free(str);
+	return -1;
+}
+
+void move_char(FILE *f, long src, long dst)
+{
+	int c;
+	fseek(f, src, SEEK_SET);
+	c = fgetc(f);
+	fseek(f, dst, SEEK_SET);
+	fputc(c, f);
+}
+
+void file_move_contents(FILE *f, long from, long to, long end)
+{
+	int c;
+	long p, q;
+	if (from < to) {
+		// in case of moving to the right side, 
+		// we start from right end and move backwards to the start
+		for (p = end, q = end + to - from; p >= from; p--, q--) {
+			move_char(f, p, q);
+		}
+	} else {
+		// otherwise, we start from the left and move towards
+		// the right
+		for (p = from, q = to; p <= end; p++, q++) {
+			move_char(f, p, q);
+		}
+	}
+}
+
+int main(int argc, char **argv)
+{
+	FILE *f;
+	int fd;
+	long pos;
+	long olen, nlen, end;
+	if (argc < 4) {
+		printf("Usage: %s [file] [needle] [replacement]\n", argv[0]);
+		printf("Replaces needle in the contents of file with replacement.\n\n");
+		return 2;
+	}
+	if (argv[2][0] == '\0') {
+		printf("%s: Invalid needle: needle can not be empty.\n", argv[0]);
+		return 3;
+	}
+	f = fopen(argv[1], "r+");
+	if (f == NULL) {
+		printf("%s: Error: Can not open file `%s` for reading.\n",
+			argv[0], argv[1]);
+		return 1;
+	}
+	pos = find_in_file(f, argv[2]);
+	if (pos == -1) {
+		printf("The string \"%s\" is not found in file `%s`\n",
+			argv[2], argv[1]);
+	} else {
+		printf("The string \"%s\" is found in file `%s` at position %ld\n", argv[2], argv[1], pos);
+		fseek(f, 0L, SEEK_END);
+		end = ftell(f);
+		olen = str_length(argv[2]);
+		nlen = str_length(argv[3]);
+		file_move_contents(f, pos + olen, pos + nlen, end - 1);
+		// write down the replacement in the right place
+		fseek(f, pos, SEEK_SET);
+		fwrite(argv[3], 1, nlen, f);
+		fseek(f, 0L, SEEK_END);
+		end = ftell(f);
+		// truncate the file to the right size
+		fd = fileno(f);
+		ftruncate(fd, end + nlen - olen);
+	}
+	fclose(f);
+	return 0;
+}
+