/*
- * 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 > GIT_OID_HEXSZ)
length = GIT_OID_HEXSZ;
- if (length % 2)
- length--;
+ for (p = 0; p < length - 1; p += 2) {
+ v = (git__fromhex(str[p + 0]) << 4)
+ | git__fromhex(str[p + 1]);
- for (p = 0; p < length; p += 2) {
- int v = (from_hex[(unsigned char)str[p + 0]] << 4)
- | from_hex[(unsigned char)str[p + 1]];
+ if (v < 0)
+ return oid_error_invalid("contains invalid characters");
+ out->id[p / 2] = (unsigned char)v;
+ }
+
+ if (length % 2) {
+ 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;
}
- for (; p < GIT_OID_HEXSZ; p += 2)
- out->id[p / 2] = 0x0;
+ 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)
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;
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);
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)
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;
return 0;
}
+int git_oid_streq(const git_oid *a, const char *str)
+{
+ git_oid id;
+
+ if (git_oid_fromstr(&id, str) < 0)
+ return -1;
+
+ return git_oid_cmp(a, &id) == 0 ? 0 : -1;
+}
+
+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;
typedef union {
static int resize_trie(git_oid_shorten *self, size_t new_size)
{
- self->nodes = realloc(self->nodes, new_size * sizeof(trie_node));
- if (self->nodes == NULL)
- return GIT_ENOMEM;
+ self->nodes = git__realloc(self->nodes, new_size * sizeof(trie_node));
+ 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)
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;
}
{
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) {
- free(os);
+ 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;
}
void git_oid_shorten_free(git_oid_shorten *os)
{
- free(os->nodes);
- free(os);
+ git__free(os->nodes);
+ git__free(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
*/
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];
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;
}
}