]> git.proxmox.com Git - libgit2.git/blobdiff - src/oid.c
Make git_oid_tostr use out buffer for NULL oid
[libgit2.git] / src / oid.c
index 4b30804307098b8ffed60f8a82c1a736bf409d0b..bbdd8541bcfbb7fe12be7e3350037f1b1f7c95fb 100644 (file)
--- a/src/oid.c
+++ b/src/oid.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2011 the libgit2 contributors
+ * Copyright (C) 2009-2012 the libgit2 contributors
  *
  * This file is part of libgit2, distributed under the GNU GPL v2 with
  * a Linking Exception. For full terms see the included COPYING file.
 #include <string.h>
 #include <limits.h>
 
-static signed char from_hex[] = {
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */
--1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */
--1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */
-};
 static char to_hex[] = "0123456789abcdef";
 
+static int oid_error_invalid(const char *msg)
+{
+       giterr_set(GITERR_INVALID, "Unable to parse OID - %s", msg);
+       return -1;
+}
+
 int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
 {
        size_t p;
        int v;
 
-       if (length < 4)
-               return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is too short");
-
        if (length > GIT_OID_HEXSZ)
                length = GIT_OID_HEXSZ;
 
        for (p = 0; p < length - 1; p += 2) {
-               v = (from_hex[(unsigned char)str[p + 0]] << 4)
-                               | from_hex[(unsigned char)str[p + 1]];
+               v = (git__fromhex(str[p + 0]) << 4)
+                               | git__fromhex(str[p + 1]);
 
                if (v < 0)
-                       return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash");
+                       return oid_error_invalid("contains invalid characters");
 
                out->id[p / 2] = (unsigned char)v;
        }
 
        if (length % 2) {
-               v = (from_hex[(unsigned char)str[p + 0]] << 4);
+               v = (git__fromhex(str[p + 0]) << 4);
                if (v < 0)
-                       return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash");
+                       return oid_error_invalid("contains invalid characters");
 
                out->id[p / 2] = (unsigned char)v;
                p += 2;
@@ -63,7 +48,7 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
 
        memset(out->id + p / 2, 0, (GIT_OID_HEXSZ - p) / 2);
 
-       return GIT_SUCCESS;
+       return 0;
 }
 
 int git_oid_fromstr(git_oid *out, const char *str)
@@ -106,16 +91,16 @@ char *git_oid_allocfmt(const git_oid *oid)
        return str;
 }
 
-char *git_oid_to_string(char *out, size_t n, const git_oid *oid)
+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) {
+       if (n > 0 && oid != NULL) {
                git_oid_fmt(str, oid);
                if (n > GIT_OID_HEXSZ)
                        n = GIT_OID_HEXSZ;
@@ -127,8 +112,9 @@ char *git_oid_to_string(char *out, size_t n, const git_oid *oid)
        return out;
 }
 
-int git_oid__parse(git_oid *oid, const char **buffer_out,
-               const char *buffer_end, const char *header)
+int git_oid__parse(
+       git_oid *oid, const char **buffer_out,
+       const char *buffer_end, const char *header)
 {
        const size_t sha_len = GIT_OID_HEXSZ;
        const size_t header_len = strlen(header);
@@ -136,20 +122,20 @@ int git_oid__parse(git_oid *oid, const char **buffer_out,
        const char *buffer = *buffer_out;
 
        if (buffer + (header_len + sha_len + 1) > buffer_end)
-               return git__throw(GIT_EOBJCORRUPTED, "Failed to parse OID. Buffer too small");
+               return -1;
 
        if (memcmp(buffer, header, header_len) != 0)
-               return git__throw(GIT_EOBJCORRUPTED, "Failed to parse OID. Buffer and header do not match");
+               return -1;
 
        if (buffer[header_len + sha_len] != '\n')
-               return git__throw(GIT_EOBJCORRUPTED, "Failed to parse OID. Buffer not terminated correctly");
+               return -1;
 
-       if (git_oid_fromstr(oid, buffer + header_len) < GIT_SUCCESS)
-               return git__throw(GIT_EOBJCORRUPTED, "Failed to parse OID. Failed to generate sha1");
+       if (git_oid_fromstr(oid, buffer + header_len) < 0)
+               return -1;
 
        *buffer_out = buffer + (header_len + sha_len + 1);
 
-       return GIT_SUCCESS;
+       return 0;
 }
 
 void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid)
@@ -172,12 +158,7 @@ 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 memcmp(a->id, b->id, sizeof(a->id));
-}
-
-int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, unsigned int len)
+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;
@@ -200,12 +181,21 @@ int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, unsigned int len)
 int git_oid_streq(const git_oid *a, const char *str)
 {
        git_oid id;
-       int error;
 
-       if ((error = git_oid_fromstr(&id, str)) < GIT_SUCCESS)
-               return git__rethrow(error, "Failed to convert '%s' to oid.", str);
+       if (git_oid_fromstr(&id, str) < 0)
+               return -1;
+
+       return git_oid_cmp(a, &id) == 0 ? 0 : -1;
+}
 
-       return git_oid_cmp(a, &id) == 0 ? GIT_SUCCESS : GIT_ERROR;
+int git_oid_iszero(const git_oid *oid_a)
+{
+       const unsigned char *a = oid_a->id;
+       unsigned int i;
+       for (i = 0; i < GIT_OID_RAWSZ; ++i, ++a)
+               if (*a != 0)
+                       return 0;
+       return 1;
 }
 
 typedef short node_index;
@@ -224,15 +214,14 @@ 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));
-       if (self->nodes == NULL)
-               return GIT_ENOMEM;
+       GITERR_CHECK_ALLOC(self->nodes);
 
        if (new_size > self->size) {
                memset(&self->nodes[self->size], 0x0, (new_size - self->size) * sizeof(trie_node));
        }
 
        self->size = new_size;
-       return GIT_SUCCESS;
+       return 0;
 }
 
 static trie_node *push_leaf(git_oid_shorten *os, node_index idx, int push_at, const char *oid)
@@ -241,7 +230,7 @@ static trie_node *push_leaf(git_oid_shorten *os, node_index idx, int push_at, co
        node_index idx_leaf;
 
        if (os->node_count >= os->size) {
-               if (resize_trie(os, os->size * 2) < GIT_SUCCESS)
+               if (resize_trie(os, os->size * 2) < 0)
                        return NULL;
        }
 
@@ -263,19 +252,19 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
 {
        git_oid_shorten *os;
 
-       os = git__malloc(sizeof(git_oid_shorten));
+       assert((size_t)((int)min_length) == min_length);
+
+       os = git__calloc(1, sizeof(git_oid_shorten));
        if (os == NULL)
                return NULL;
 
-       memset(os, 0x0, sizeof(git_oid_shorten));
-
-       if (resize_trie(os, 16) < GIT_SUCCESS) {
+       if (resize_trie(os, 16) < 0) {
                git__free(os);
                return NULL;
        }
 
        os->node_count = 1;
-       os->min_length = min_length;
+       os->min_length = (int)min_length;
 
        return os;
 }
@@ -304,7 +293,7 @@ void git_oid_shorten_free(git_oid_shorten *os)
  *     - Each normal node points to 16 children (one for each possible
  *     character in the oid). This is *not* stored in an array of
  *     pointers, because in a 64-bit arch this would be sucking
- *     16*sizeof(void*) = 128 bytes of memory per node, which is fucking
+ *     16*sizeof(void*) = 128 bytes of memory per node, which is
  *     insane. What we do is store Node Indexes, and use these indexes
  *     to look up each node in the om->index array. These indexes are
  *     signed shorts, so this limits the amount of unique OIDs that
@@ -333,24 +322,27 @@ void git_oid_shorten_free(git_oid_shorten *os)
  */
 int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
 {
-       int i, is_leaf;
+       int i;
+       bool is_leaf;
        node_index idx;
 
        if (os->full)
-               return GIT_ENOMEM;
+               return -1;
 
        if (text_oid == NULL)
                return os->min_length;
 
        idx = 0;
-       is_leaf = 0;
+       is_leaf = false;
 
        for (i = 0; i < GIT_OID_HEXSZ; ++i) {
-               int c = from_hex[(int)text_oid[i]];
+               int c = git__fromhex(text_oid[i]);
                trie_node *node;
 
-               if (c == -1)
-                       return git__throw(GIT_ENOTOID, "Failed to shorten OID. Invalid hex value");
+               if (c == -1) {
+                       giterr_set(GITERR_INVALID, "Unable to shorten OID - invalid hex value");
+                       return -1;
+               }
 
                node = &os->nodes[idx];
 
@@ -360,23 +352,22 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
                        tail = node->tail;
                        node->tail = NULL;
 
-                       node = push_leaf(os, idx, from_hex[(int)tail[0]], &tail[1]);
-                       if (node == NULL)
-                               return GIT_ENOMEM;
+                       node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]);
+                       GITERR_CHECK_ALLOC(node);
                }
 
                if (node->children[c] == 0) {
                        if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL)
-                               return GIT_ENOMEM;
+                               return -1;
                        break;
                }
 
                idx = node->children[c];
-               is_leaf = 0;
+               is_leaf = false;
 
                if (idx < 0) {
                        node->children[c] = idx = -idx;
-                       is_leaf = 1;
+                       is_leaf = true;
                }
        }