summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blob.c6
-rw-r--r--src/blob.h1
-rw-r--r--src/buffer.c7
-rw-r--r--src/buffer.h2
-rw-r--r--src/crlf.c60
-rw-r--r--src/filter.c31
6 files changed, 51 insertions, 56 deletions
diff --git a/src/blob.c b/src/blob.c
index e1f4a7f6a..b67f8afa5 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -25,6 +25,12 @@ size_t git_blob_rawsize(git_blob *blob)
return blob->odb_object->raw.len;
}
+int git_blob__getbuf(git_buf *buffer, git_blob *blob)
+{
+ return git_buf_set(
+ buffer, blob->odb_object->raw.data, blob->odb_object->raw.len);
+}
+
void git_blob__free(git_blob *blob)
{
git_odb_object_free(blob->odb_object);
diff --git a/src/blob.h b/src/blob.h
index f810b506b..0305e9473 100644
--- a/src/blob.h
+++ b/src/blob.h
@@ -19,5 +19,6 @@ struct git_blob {
void git_blob__free(git_blob *blob);
int git_blob__parse(git_blob *blob, git_odb_object *obj);
+int git_blob__getbuf(git_buf *buffer, git_blob *blob);
#endif
diff --git a/src/buffer.c b/src/buffer.c
index 68cc39388..3098f6d68 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -389,3 +389,10 @@ void git_buf_rtrim(git_buf *buf)
buf->ptr[buf->size] = '\0';
}
+
+int git_buf_cmp(const git_buf *a, const git_buf *b)
+{
+ int result = memcmp(a->ptr, b->ptr, min(a->size, b->size));
+ return (result != 0) ? result :
+ (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0;
+}
diff --git a/src/buffer.h b/src/buffer.h
index 3e9cb1713..3cdd794af 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -118,4 +118,6 @@ GIT_INLINE(int) git_buf_rfind_next(git_buf *buf, char ch)
/* Remove whitespace from the end of the buffer */
void git_buf_rtrim(git_buf *buf);
+int git_buf_cmp(const git_buf *a, const git_buf *b);
+
#endif
diff --git a/src/crlf.c b/src/crlf.c
index 404156d6a..f0ec7b736 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -104,52 +104,32 @@ static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, con
static int drop_crlf(git_buf *dest, const git_buf *source)
{
- size_t psize = source->size - 1;
- size_t i = 0;
+ const char *scan = source->ptr, *next;
+ const char *scan_end = source->ptr + source->size;
- /* Initial scan: see if we can reach the end of the document
- * without finding a single carriage return */
- while (i < psize && source->ptr[i] != '\r')
- i++;
-
- /* Clean file? Tell the library to skip this filter */
- if (i == psize)
- return -1;
-
- /* Main scan loop. Keep moving forward until we find a carriage
- * return, and then copy the whole chunk to the destination
- * buffer.
- *
- * Note that we only scan until `size - 1`, because we cannot drop a
- * carriage return if it's the last character in the file (what a weird
- * file, anyway)
+ /* Main scan loop. Find the next carriage return and copy the
+ * whole chunk up to that point to the destination buffer.
*/
- while (i < psize) {
- size_t org = i;
+ while ((next = memchr(scan, '\r', scan_end - scan)) != NULL) {
+ /* copy input up to \r */
+ if (next > scan)
+ git_buf_put(dest, scan, next - scan);
- while (i < psize && source->ptr[i] != '\r')
- i++;
-
- if (i > org)
- git_buf_put(dest, source->ptr + org, i - org);
-
- /* We found a carriage return. Is the next character a newline?
- * If it is, we just keep moving. The newline will be copied
- * to the dest in the next chunk.
- *
- * If it's not a newline, we need to insert the carriage return
- * into the dest buffer, because we don't drop lone CRs.
- */
- if (source->ptr[i + 1] != '\n') {
+ /* Do not drop \r unless it is followed by \n */
+ if (*(next + 1) != '\n')
git_buf_putc(dest, '\r');
- }
-
- i++;
+
+ scan = next + 1;
}
- /* Copy the last character in the file */
- git_buf_putc(dest, source->ptr[psize]);
- return 0;
+ /* If there was no \r, then tell the library to skip this filter */
+ if (scan == source->ptr)
+ return -1;
+
+ /* Copy remaining input into dest */
+ git_buf_put(dest, scan, scan_end - scan);
+
+ return git_buf_lasterror(dest);
}
static int crlf_apply_to_odb(git_filter *self, git_buf *dest, const git_buf *source)
diff --git a/src/filter.c b/src/filter.c
index f93730acb..f0ee1ad39 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -12,7 +12,7 @@
#include "repository.h"
#include "git2/config.h"
-/* Fresh from Core Git. I wonder what we could use this for... */
+/* Tweaked from Core Git. I wonder what we could use this for... */
void git_text_gather_stats(git_text_stats *stats, const git_buf *text)
{
size_t i;
@@ -27,20 +27,20 @@ void git_text_gather_stats(git_text_stats *stats, const git_buf *text)
if (i + 1 < text->size && text->ptr[i + 1] == '\n')
stats->crlf++;
-
- continue;
}
- if (c == '\n') {
+ else if (c == '\n')
stats->lf++;
- continue;
- }
- if (c == 127)
+ else if (c == 0x85)
+ /* Unicode CR+LF */
+ stats->crlf++;
+
+ else if (c == 127)
/* DEL */
stats->nonprintable++;
- else if (c < 32) {
+ else if (c <= 0x1F || (c >= 0x80 && c <= 0x9F)) {
switch (c) {
/* BS, HT, ESC and FF */
case '\b': case '\t': case '\033': case '\014':
@@ -53,6 +53,7 @@ void git_text_gather_stats(git_text_stats *stats, const git_buf *text)
stats->nonprintable++;
}
}
+
else
stats->printable++;
}
@@ -118,7 +119,7 @@ void git_filters_free(git_vector *filters)
int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
{
- unsigned int src, dst, i;
+ unsigned int i, src;
git_buf *dbuffer[2];
dbuffer[0] = source;
@@ -138,28 +139,26 @@ int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
for (i = 0; i < filters->length; ++i) {
git_filter *filter = git_vector_get(filters, i);
- dst = (src + 1) % 2;
+ unsigned int dst = 1 - src;
git_buf_clear(dbuffer[dst]);
- /* Apply the filter, from dbuffer[src] to dbuffer[dst];
+ /* Apply the filter from dbuffer[src] to the other buffer;
* if the filtering is canceled by the user mid-filter,
* we skip to the next filter without changing the source
* of the double buffering (so that the text goes through
* cleanly).
*/
- if (filter->apply(filter, dbuffer[dst], dbuffer[src]) == 0) {
- src = (src + 1) % 2;
- }
+ if (filter->apply(filter, dbuffer[dst], dbuffer[src]) == 0)
+ src = dst;
if (git_buf_oom(dbuffer[dst]))
return GIT_ENOMEM;
}
/* Ensure that the output ends up in dbuffer[1] (i.e. the dest) */
- if (dst != 1) {
+ if (src != 1)
git_buf_swap(dest, source);
- }
return GIT_SUCCESS;
}