Commit b7c891c629d298f2d82310d8ced2ee2e48084213

Shawn O. Pearce 2008-11-03T17:31:16

Add git_oid_cpy, git_oid_cmp as inline functions These are easily built off the standard C library functions memcpy and memcmp. By marking these inline we stand a good chance of the C compiler replacing the entire thing with tight machine code, because many compilers will actually inline a memcmp or memcpy when the 3rd argument (the size) is a constant value. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

diff --git a/api.doxygen b/api.doxygen
index b27d0a8..8dfd652 100644
--- a/api.doxygen
+++ b/api.doxygen
@@ -17,6 +17,7 @@ CASE_SENSE_NAMES      = NO
 
 PREDEFINED = \
   "GIT_EXTERN(x)=x" \
+  "GIT_INLINE(x)=x" \
   "GIT_BEGIN_DECL=" \
   "GIT_END_DECL=" \
   DOXYGEN=
diff --git a/include/git/common.h b/include/git/common.h
index 60f4720..ca65c74 100644
--- a/include/git/common.h
+++ b/include/git/common.h
@@ -45,6 +45,9 @@
 # define GIT_EXTERN(type) extern type
 #endif
 
+/** Declare a function as always inlined. */
+# define GIT_INLINE(type) static inline type
+
 /** Declare a function's takes printf style arguments. */
 #ifdef __GNUC__
 # define GIT_FORMAT_PRINTF(a,b) __attribute__((format (printf, a, b)))
diff --git a/include/git/oid.h b/include/git/oid.h
index 40a7c27..1ff4954 100644
--- a/include/git/oid.h
+++ b/include/git/oid.h
@@ -59,7 +59,31 @@ GIT_EXTERN(int) git_oid_mkstr(git_oid *out, const char *str);
  * @param out oid structure the result is written into.
  * @param raw the raw input bytes to be copied.
  */
-GIT_EXTERN(void) git_oid_mkraw(git_oid *out, const unsigned char *raw);
+GIT_INLINE(void) git_oid_mkraw(git_oid *out, const unsigned char *raw)
+{
+	memcpy(out->id, raw, sizeof(out->id));
+}
+
+/**
+ * Copy an oid from one structure to another.
+ * @param out oid structure the result is written into.
+ * @param src oid structure to copy from.
+ */
+GIT_INLINE(void) git_oid_cpy(git_oid *out, const git_oid *src)
+{
+	memcpy(out->id, src->id, sizeof(out->id));
+}
+
+/**
+ * Compare two oid structures.
+ * @param a first oid structure.
+ * @param b second oid structure.
+ * @return <0, 0, >0 if a < b, a == b, a > b.
+ */
+GIT_INLINE(int) git_oid_cmp(const git_oid *a, const git_oid *b)
+{
+	return memcmp(a->id, b->id, sizeof(a->id));
+}
 
 /** @} */
 GIT_END_DECL
diff --git a/include/git/os/unix.h b/include/git/os/unix.h
index 351cfa4..dd58389 100644
--- a/include/git/os/unix.h
+++ b/include/git/os/unix.h
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <time.h>
+#include <string.h>
 
 /**
  * @file git/os/unix.h
diff --git a/src/oid.c b/src/oid.c
index 72b9511..e235f89 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -57,8 +57,3 @@ int git_oid_mkstr(git_oid *out, const char *str)
 	}
 	return GIT_SUCCESS;
 }
-
-void git_oid_mkraw(git_oid *out, const unsigned char *raw)
-{
-	memcpy(out->id, raw, sizeof(out->id));
-}
diff --git a/tests/t0000-oid.c b/tests/t0000-oid.c
index 25263fd..6249655 100644
--- a/tests/t0000-oid.c
+++ b/tests/t0000-oid.c
@@ -81,3 +81,72 @@ BEGIN_TEST(valid_raw)
 	git_oid_mkraw(&out, exp);
 	must_pass(memcmp(out.id, exp, sizeof(out.id)));
 END_TEST
+
+BEGIN_TEST(copy_oid)
+	git_oid a, b;
+	unsigned char exp[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+	};
+
+	memset(&b, 0, sizeof(b));
+	git_oid_mkraw(&a, exp);
+	git_oid_cpy(&b, &a);
+	must_pass(memcmp(a.id, exp, sizeof(a.id)));
+END_TEST
+
+BEGIN_TEST(cmp_oid_lt)
+	git_oid a, b;
+	unsigned char a_in[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+	};
+	unsigned char b_in[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xf0,
+	};
+
+	git_oid_mkraw(&a, a_in);
+	git_oid_mkraw(&b, b_in);
+	must_be_true(git_oid_cmp(&a, &b) < 0);
+END_TEST
+
+BEGIN_TEST(cmp_oid_eq)
+	git_oid a, b;
+	unsigned char a_in[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+	};
+
+	git_oid_mkraw(&a, a_in);
+	git_oid_mkraw(&b, a_in);
+	must_be_true(git_oid_cmp(&a, &b) == 0);
+END_TEST
+
+BEGIN_TEST(cmp_oid_gt)
+	git_oid a, b;
+	unsigned char a_in[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xe0,
+	};
+	unsigned char b_in[] = {
+		0x16, 0xa6, 0x77, 0x70, 0xb7,
+		0xd8, 0xd7, 0x23, 0x17, 0xc4,
+		0xb7, 0x75, 0x21, 0x3c, 0x23,
+		0xa8, 0xbd, 0x74, 0xf5, 0xd0,
+	};
+
+	git_oid_mkraw(&a, a_in);
+	git_oid_mkraw(&b, b_in);
+	must_be_true(git_oid_cmp(&a, &b) > 0);
+END_TEST
diff --git a/tests/test_lib.h b/tests/test_lib.h
index 41cb5ab..52121c9 100644
--- a/tests/test_lib.h
+++ b/tests/test_lib.h
@@ -90,3 +90,11 @@ extern void test_die(const char *fmt, ...)
  */
 #define must_fail(expr) \
 	if (!(expr)) test_die("line %d: %s", __LINE__, #expr)
+
+/**
+ * Evaluate an expression which must produce a true result.
+ *
+ * @param expr the expression to evaluate, and test the result of.
+ */
+#define must_be_true(expr) \
+	if (!(expr)) test_die("line %d: %s", __LINE__, #expr)