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 )