summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar René Scharfe <rene.scharfe@lsrfire.ath.cx>2007-09-07 00:32:54 +0200
committerLibravatar Junio C Hamano <gitster@pobox.com>2007-09-06 22:46:00 -0700
commitb21b9f1de313acb5550c070911ae58c735cdb451 (patch)
tree1c271b15eff9d772828cd634f3a1f6303bc49726
parentRemove unused function convert_sha1_file() (diff)
downloadtgif-b21b9f1de313acb5550c070911ae58c735cdb451.tar.xz
add memmem()
memmem() is a nice GNU extension for searching a length limited string in another one. This compat version is based on the version found in glibc 2.2 (GPL 2); I only removed the optimization of checking the first char by hand, and generally tried to keep the code simple. We can add it back if memcmp shows up high in a profile, but for now I prefer to keep it (almost trivially) simple. Since I don't really know which platforms beside those with a glibc have their own memmem(), I used a heuristic: if NO_STRCASESTR is set, then NO_MEMMEM is set, too. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Makefile11
-rw-r--r--compat/memmem.c29
-rw-r--r--git-compat-util.h6
3 files changed, 46 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 51af531c9a..bae073fe37 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,8 @@ all::
#
# Define NO_STRCASESTR if you don't have strcasestr.
#
+# Define NO_MEMMEM if you don't have memmem.
+#
# Define NO_STRLCPY if you don't have strlcpy.
#
# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@@ -402,6 +404,7 @@ ifeq ($(uname_S),SunOS)
NEEDS_NSL = YesPlease
SHELL_PATH = /bin/bash
NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
NO_HSTRERROR = YesPlease
ifeq ($(uname_R),5.8)
NEEDS_LIBICONV = YesPlease
@@ -424,6 +427,7 @@ ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease
NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -442,6 +446,7 @@ ifeq ($(uname_S),FreeBSD)
endif
ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease
+ NO_MEMMEM = YesPlease
NEEDS_LIBICONV = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
@@ -456,6 +461,7 @@ ifeq ($(uname_S),NetBSD)
endif
ifeq ($(uname_S),AIX)
NO_STRCASESTR=YesPlease
+ NO_MEMMEM = YesPlease
NO_STRLCPY = YesPlease
NEEDS_LIBICONV=YesPlease
endif
@@ -467,6 +473,7 @@ ifeq ($(uname_S),IRIX64)
NO_IPV6=YesPlease
NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease
+ NO_MEMMEM = YesPlease
NO_STRLCPY = YesPlease
NO_SOCKADDR_STORAGE=YesPlease
SHELL_PATH=/usr/gnu/bin/bash
@@ -661,6 +668,10 @@ ifdef NO_HSTRERROR
COMPAT_CFLAGS += -DNO_HSTRERROR
COMPAT_OBJS += compat/hstrerror.o
endif
+ifdef NO_MEMMEM
+ COMPAT_CFLAGS += -DNO_MEMMEM
+ COMPAT_OBJS += compat/memmem.o
+endif
ifeq ($(TCLTK_PATH),)
NO_TCLTK=NoThanks
diff --git a/compat/memmem.c b/compat/memmem.c
new file mode 100644
index 0000000000..cd0d877364
--- /dev/null
+++ b/compat/memmem.c
@@ -0,0 +1,29 @@
+#include "../git-compat-util.h"
+
+void *gitmemmem(const void *haystack, size_t haystack_len,
+ const void *needle, size_t needle_len)
+{
+ const char *begin = haystack;
+ const char *last_possible = begin + haystack_len - needle_len;
+
+ /*
+ * The first occurrence of the empty string is deemed to occur at
+ * the beginning of the string.
+ */
+ if (needle_len == 0)
+ return (void *)begin;
+
+ /*
+ * Sanity check, otherwise the loop might search through the whole
+ * memory.
+ */
+ if (haystack_len < needle_len)
+ return NULL;
+
+ for (; begin <= last_possible; begin++) {
+ if (!memcmp(begin, needle, needle_len))
+ return (void *)begin;
+ }
+
+ return NULL;
+}
diff --git a/git-compat-util.h b/git-compat-util.h
index ca0a597a28..1bfbdeb94f 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -172,6 +172,12 @@ extern uintmax_t gitstrtoumax(const char *, char **, int);
extern const char *githstrerror(int herror);
#endif
+#ifdef NO_MEMMEM
+#define memmem gitmemmem
+void *gitmemmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+#endif
+
extern void release_pack_memory(size_t, int);
static inline char* xstrdup(const char *str)