]> git.proxmox.com Git - libgit2.git/blobdiff - src/oid.c
push: remove own copy of callbacks
[libgit2.git] / src / oid.c
index 1bf74b963e7812138cdf77230173d6f9a4f2c34c..9fe2ebb6522e19a0af083c609aba330ca1e162b9 100644 (file)
--- a/src/oid.c
+++ b/src/oid.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2012 the libgit2 contributors
+ * Copyright (C) the libgit2 contributors. All rights reserved.
  *
  * This file is part of libgit2, distributed under the GNU GPL v2 with
  * a Linking Exception. For full terms see the included COPYING file.
@@ -8,6 +8,7 @@
 #include "common.h"
 #include "git2/oid.h"
 #include "repository.h"
+#include "global.h"
 #include <string.h>
 #include <limits.h>
 
@@ -24,33 +25,32 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
        size_t p;
        int v;
 
-       if (length > GIT_OID_HEXSZ)
-               length = GIT_OID_HEXSZ;
+       assert(out && str);
 
-       for (p = 0; p < length - 1; p += 2) {
-               v = (git__fromhex(str[p + 0]) << 4)
-                               | git__fromhex(str[p + 1]);
+       if (!length)
+               return oid_error_invalid("too short");
 
-               if (v < 0)
-                       return oid_error_invalid("contains invalid characters");
+       if (length > GIT_OID_HEXSZ)
+               return oid_error_invalid("too long");
 
-               out->id[p / 2] = (unsigned char)v;
-       }
+       memset(out->id, 0, GIT_OID_RAWSZ);
 
-       if (length % 2) {
-               v = (git__fromhex(str[p + 0]) << 4);
+       for (p = 0; p < length; p++) {
+               v = git__fromhex(str[p]);
                if (v < 0)
                        return oid_error_invalid("contains invalid characters");
 
-               out->id[p / 2] = (unsigned char)v;
-               p += 2;
+               out->id[p / 2] |= (unsigned char)(v << (p % 2 ? 0 : 4));
        }
 
-       memset(out->id + p / 2, 0, (GIT_OID_HEXSZ - p) / 2);
-
        return 0;
 }
 
+int git_oid_fromstrp(git_oid *out, const char *str)
+{
+       return git_oid_fromstrn(out, str, strlen(str));
+}
+
 int git_oid_fromstr(git_oid *out, const char *str)
 {
        return git_oid_fromstrn(out, str, GIT_OID_HEXSZ);
@@ -63,12 +63,31 @@ GIT_INLINE(char) *fmt_one(char *str, unsigned int val)
        return str;
 }
 
-void git_oid_fmt(char *str, const git_oid *oid)
+void git_oid_nfmt(char *str, size_t n, const git_oid *oid)
 {
-       size_t i;
+       size_t i, max_i;
+
+       if (!oid) {
+               memset(str, 0, n);
+               return;
+       }
+       if (n > GIT_OID_HEXSZ) {
+               memset(&str[GIT_OID_HEXSZ], 0, n - GIT_OID_HEXSZ);
+               n = GIT_OID_HEXSZ;
+       }
+
+       max_i = n / 2;
 
-       for (i = 0; i < sizeof(oid->id); i++)
+       for (i = 0; i < max_i; i++)
                str = fmt_one(str, oid->id[i]);
+
+       if (n & 1)
+               *str++ = to_hex[oid->id[i] >> 4];
+}
+
+void git_oid_fmt(char *str, const git_oid *oid)
+{
+       git_oid_nfmt(str, GIT_OID_HEXSZ, oid);
 }
 
 void git_oid_pathfmt(char *str, const git_oid *oid)
@@ -81,33 +100,32 @@ void git_oid_pathfmt(char *str, const git_oid *oid)
                str = fmt_one(str, oid->id[i]);
 }
 
+char *git_oid_tostr_s(const git_oid *oid)
+{
+       char *str = GIT_GLOBAL->oid_fmt;
+       git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
+       return str;
+}
+
 char *git_oid_allocfmt(const git_oid *oid)
 {
        char *str = git__malloc(GIT_OID_HEXSZ + 1);
        if (!str)
                return NULL;
-       git_oid_fmt(str, oid);
-       str[GIT_OID_HEXSZ] = '\0';
+       git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
        return str;
 }
 
 char *git_oid_tostr(char *out, size_t n, const git_oid *oid)
 {
-       char str[GIT_OID_HEXSZ];
-
-       if (!out || n == 0 || !oid)
+       if (!out || n == 0)
                return "";
 
-       n--; /* allow room for terminating NUL */
-
-       if (n > 0) {
-               git_oid_fmt(str, oid);
-               if (n > GIT_OID_HEXSZ)
-                       n = GIT_OID_HEXSZ;
-               memcpy(out, str, n);
-       }
+       if (n > GIT_OID_HEXSZ + 1)
+               n = GIT_OID_HEXSZ + 1;
 
-       out[n] = '\0';
+       git_oid_nfmt(out, n - 1, oid); /* allow room for terminating NUL */
+       out[n - 1] = '\0';
 
        return out;
 }
@@ -158,18 +176,31 @@ void git_oid_cpy(git_oid *out, const git_oid *src)
        memcpy(out->id, src->id, sizeof(out->id));
 }
 
+int git_oid_cmp(const git_oid *a, const git_oid *b)
+{
+       return git_oid__cmp(a, b);
+}
+
+int git_oid_equal(const git_oid *a, const git_oid *b)
+{
+       return (git_oid__cmp(a, b) == 0);
+}
+
 int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
 {
        const unsigned char *a = oid_a->id;
        const unsigned char *b = oid_b->id;
 
-       do {
+       if (len > GIT_OID_HEXSZ)
+               len = GIT_OID_HEXSZ;
+
+       while (len > 1) {
                if (*a != *b)
                        return 1;
                a++;
                b++;
                len -= 2;
-       } while (len > 1);
+       };
 
        if (len)
                if ((*a ^ *b) & 0xf0)
@@ -178,14 +209,31 @@ int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
        return 0;
 }
 
-int git_oid_streq(const git_oid *a, const char *str)
+int git_oid_strcmp(const git_oid *oid_a, const char *str)
 {
-       git_oid id;
+       const unsigned char *a;
+       unsigned char strval;
+       int hexval;
 
-       if (git_oid_fromstr(&id, str) < 0)
-               return -1;
+       for (a = oid_a->id; *str && (a - oid_a->id) < GIT_OID_RAWSZ; ++a) {
+               if ((hexval = git__fromhex(*str++)) < 0)
+                       return -1;
+               strval = (unsigned char)(hexval << 4);
+               if (*str) {
+                       if ((hexval = git__fromhex(*str++)) < 0)
+                               return -1;
+                       strval |= hexval;
+               }
+               if (*a != strval)
+                       return (*a - strval);
+       }
 
-       return git_oid_cmp(a, &id) == 0 ? 0 : -1;
+       return 0;
+}
+
+int git_oid_streq(const git_oid *oid_a, const char *str)
+{
+       return git_oid_strcmp(oid_a, str) == 0 ? 0 : -1;
 }
 
 int git_oid_iszero(const git_oid *oid_a)
@@ -213,7 +261,7 @@ struct git_oid_shorten {
 
 static int resize_trie(git_oid_shorten *self, size_t new_size)
 {
-       self->nodes = git__realloc(self->nodes, new_size * sizeof(trie_node));
+       self->nodes = git__reallocarray(self->nodes, new_size, sizeof(trie_node));
        GITERR_CHECK_ALLOC(self->nodes);
 
        if (new_size > self->size) {
@@ -236,8 +284,10 @@ static trie_node *push_leaf(git_oid_shorten *os, node_index idx, int push_at, co
 
        idx_leaf = (node_index)os->node_count++;
 
-       if (os->node_count == SHRT_MAX)
+       if (os->node_count == SHRT_MAX) {
                os->full = 1;
+        return NULL;
+    }
 
        node = &os->nodes[idx];
        node->children[push_at] = -idx_leaf;
@@ -271,6 +321,9 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
 
 void git_oid_shorten_free(git_oid_shorten *os)
 {
+       if (os == NULL)
+               return;
+
        git__free(os->nodes);
        git__free(os);
 }
@@ -326,8 +379,10 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
        bool is_leaf;
        node_index idx;
 
-       if (os->full)
+       if (os->full) {
+               giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
                return -1;
+       }
 
        if (text_oid == NULL)
                return os->min_length;
@@ -353,12 +408,19 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
                        node->tail = NULL;
 
                        node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]);
-                       GITERR_CHECK_ALLOC(node);
+                       if (node == NULL) {
+                               if (os->full)
+                                       giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
+                               return -1;
+                       }
                }
 
                if (node->children[c] == 0) {
-                       if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL)
+                       if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL) {
+                               if (os->full)
+                                       giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
                                return -1;
+                       }
                        break;
                }