aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/argz/argz_replace.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/argz/argz_replace.c')
-rw-r--r--newlib/libc/argz/argz_replace.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/newlib/libc/argz/argz_replace.c b/newlib/libc/argz/argz_replace.c
new file mode 100644
index 0000000..92979e6
--- /dev/null
+++ b/newlib/libc/argz/argz_replace.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <argz.h>
+
+extern int buf_findstr(const char *str, char **buf, size_t *buf_len);
+
+error_t
+argz_replace (char **argz, size_t *argz_len, const char *str, const char *with, unsigned *replace_count)
+{
+ const int str_len = strlen(str);
+ const int with_len = strlen(with);
+ const int len_diff = with_len - str_len;
+
+ char *buf_iter = *argz;
+ size_t buf_len = *argz_len;
+ char *last_iter = NULL;
+ char *new_argz = NULL;
+ size_t new_argz_len = 0;
+ char *new_argz_iter = NULL;
+
+ *replace_count = 0;
+ new_argz_len = *argz_len;
+
+ while(buf_len)
+ {
+ if(buf_findstr(str, &buf_iter, &buf_len))
+ {
+ *replace_count += 1;
+ new_argz_len += len_diff;
+ }
+ }
+
+ if (*replace_count)
+ {
+ new_argz = (char *)malloc(new_argz_len);
+
+ buf_iter = *argz;
+ buf_len = *argz_len;
+ last_iter = buf_iter;
+ new_argz_iter = new_argz;
+
+ while(buf_len)
+ {
+ if (buf_findstr(str, &buf_iter, &buf_len))
+ {
+ /* copy everything up to, but not including str, from old argz to
+ new argz. */
+ memcpy(new_argz_iter, last_iter, buf_iter - last_iter - str_len);
+ new_argz_iter += (buf_iter - last_iter - str_len);
+ /* copy replacement string. */
+ memcpy(new_argz_iter, with, with_len);
+ new_argz_iter += with_len;
+ last_iter = buf_iter;
+ }
+ }
+ /* copy everything after last occurrence of str. */
+ memcpy(new_argz_iter, last_iter, *argz + *argz_len - last_iter);
+
+ /* reallocate argz, and copy over the new value. */
+ if(!(*argz = (char *)realloc(*argz, new_argz_len)))
+ return ENOMEM;
+
+ memcpy(*argz, new_argz, new_argz_len);
+ *argz_len = new_argz_len;
+
+ if (*argz_len == 0)
+ {
+ free(*argz);
+ *argz = NULL;
+ }
+ free(new_argz);
+ }
+
+ return 0;
+}