Git-Raw
view release on metacpan or search on metacpan
deps/libgit2/src/util/str.c view on Meta::CPAN
/* if we find mixed line endings, carry on */
if (copylen && next[-1] == '\r')
copylen--;
GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
if (git_str_grow_by(tgt, alloclen) < 0)
return -1;
if (copylen) {
memcpy(tgt->ptr + tgt->size, scan, copylen);
tgt->size += copylen;
}
tgt->ptr[tgt->size++] = '\r';
tgt->ptr[tgt->size++] = '\n';
}
tgt->ptr[tgt->size] = '\0';
return git_str_put(tgt, scan, end - scan);
}
int git_str_common_prefix(git_str *buf, char *const *const strings, size_t count)
{
size_t i;
const char *str, *pfx;
git_str_clear(buf);
if (!strings || !count)
return 0;
/* initialize common prefix to first string */
if (git_str_sets(buf, strings[0]) < 0)
return -1;
/* go through the rest of the strings, truncating to shared prefix */
for (i = 1; i < count; ++i) {
for (str = strings[i], pfx = buf->ptr;
*str && *str == *pfx;
str++, pfx++)
/* scanning */;
git_str_truncate(buf, pfx - buf->ptr);
if (!buf->size)
break;
}
return 0;
}
int git_str_is_binary(const git_str *buf)
{
const char *scan = buf->ptr, *end = buf->ptr + buf->size;
git_str_bom_t bom;
int printable = 0, nonprintable = 0;
scan += git_str_detect_bom(&bom, buf);
if (bom > GIT_STR_BOM_UTF8)
return 1;
while (scan < end) {
unsigned char c = *scan++;
/* Printable characters are those above SPACE (0x1F) excluding DEL,
* and including BS, ESC and FF.
*/
if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014')
printable++;
else if (c == '\0')
return true;
else if (!git__isspace(c))
nonprintable++;
}
return ((printable >> 7) < nonprintable);
}
int git_str_contains_nul(const git_str *buf)
{
return (memchr(buf->ptr, '\0', buf->size) != NULL);
}
int git_str_detect_bom(git_str_bom_t *bom, const git_str *buf)
{
const char *ptr;
size_t len;
*bom = GIT_STR_BOM_NONE;
/* need at least 2 bytes to look for any BOM */
if (buf->size < 2)
return 0;
ptr = buf->ptr;
len = buf->size;
switch (*ptr++) {
case 0:
if (len >= 4 && ptr[0] == 0 && ptr[1] == '\xFE' && ptr[2] == '\xFF') {
*bom = GIT_STR_BOM_UTF32_BE;
return 4;
}
break;
case '\xEF':
if (len >= 3 && ptr[0] == '\xBB' && ptr[1] == '\xBF') {
*bom = GIT_STR_BOM_UTF8;
return 3;
}
break;
case '\xFE':
if (*ptr == '\xFF') {
*bom = GIT_STR_BOM_UTF16_BE;
return 2;
}
break;
case '\xFF':
if (*ptr != '\xFE')
break;
if (len >= 4 && ptr[1] == 0 && ptr[2] == 0) {
*bom = GIT_STR_BOM_UTF32_LE;
return 4;
} else {
*bom = GIT_STR_BOM_UTF16_LE;
return 2;
}
break;
default:
break;
}
return 0;
}
bool git_str_gather_text_stats(
git_str_text_stats *stats, const git_str *buf, bool skip_bom)
{
const char *scan = buf->ptr, *end = buf->ptr + buf->size;
int skip;
memset(stats, 0, sizeof(*stats));
/* BOM detection */
skip = git_str_detect_bom(&stats->bom, buf);
if (skip_bom)
scan += skip;
/* Ignore EOF character */
if (buf->size > 0 && end[-1] == '\032')
end--;
/* Counting loop */
while (scan < end) {
unsigned char c = *scan++;
if (c > 0x1F && c != 0x7F)
stats->printable++;
else switch (c) {
case '\0':
stats->nul++;
stats->nonprintable++;
break;
case '\n':
stats->lf++;
break;
case '\r':
stats->cr++;
if (scan < end && *scan == '\n')
stats->crlf++;
break;
case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
stats->printable++;
break;
default:
stats->nonprintable++;
break;
}
}
/* Treat files with a bare CR as binary */
return (stats->cr != stats->crlf || stats->nul > 0 ||
((stats->printable >> 7) < stats->nonprintable));
}
( run in 0.757 second using v1.01-cache-2.11-cpan-39bf76dae61 )