]>
git.proxmox.com Git - libgit2.git/blob - src/buf_text.c
2 * Copyright (C) 2009-2012 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
9 int git_buf_text_puts_escaped(
12 const char *esc_chars
,
16 size_t total
= 0, esc_len
= strlen(esc_with
), count
;
21 for (scan
= string
; *scan
; ) {
22 /* count run of non-escaped characters */
23 count
= strcspn(scan
, esc_chars
);
26 /* count run of escaped characters */
27 count
= strspn(scan
, esc_chars
);
28 total
+= count
* (esc_len
+ 1);
32 if (git_buf_grow(buf
, buf
->size
+ total
+ 1) < 0)
35 for (scan
= string
; *scan
; ) {
36 count
= strcspn(scan
, esc_chars
);
38 memmove(buf
->ptr
+ buf
->size
, scan
, count
);
42 for (count
= strspn(scan
, esc_chars
); count
> 0; --count
) {
43 /* copy escape sequence */
44 memmove(buf
->ptr
+ buf
->size
, esc_with
, esc_len
);
46 /* copy character to be escaped */
47 buf
->ptr
[buf
->size
] = *scan
;
53 buf
->ptr
[buf
->size
] = '\0';
58 void git_buf_text_unescape(git_buf
*buf
)
60 buf
->size
= git__unescape(buf
->ptr
);
63 int git_buf_text_common_prefix(git_buf
*buf
, const git_strarray
*strings
)
66 const char *str
, *pfx
;
70 if (!strings
|| !strings
->count
)
73 /* initialize common prefix to first string */
74 if (git_buf_sets(buf
, strings
->strings
[0]) < 0)
77 /* go through the rest of the strings, truncating to shared prefix */
78 for (i
= 1; i
< strings
->count
; ++i
) {
80 for (str
= strings
->strings
[i
], pfx
= buf
->ptr
;
81 *str
&& *str
== *pfx
; str
++, pfx
++)
84 git_buf_truncate(buf
, pfx
- buf
->ptr
);
93 bool git_buf_text_is_binary(const git_buf
*buf
)
95 const char *scan
= buf
->ptr
, *end
= buf
->ptr
+ buf
->size
;
96 int printable
= 0, nonprintable
= 0;
99 unsigned char c
= *scan
++;
101 if (c
> 0x1F && c
< 0x7F)
105 else if (!git__isspace(c
))
109 return ((printable
>> 7) < nonprintable
);
112 int git_buf_text_detect_bom(git_bom_t
*bom
, const git_buf
*buf
, size_t offset
)
118 /* need at least 2 bytes after offset to look for any BOM */
119 if (buf
->size
< offset
+ 2)
122 ptr
= buf
->ptr
+ offset
;
123 len
= buf
->size
- offset
;
127 if (len
>= 4 && ptr
[0] == 0 && ptr
[1] == '\xFE' && ptr
[2] == '\xFF') {
128 *bom
= GIT_BOM_UTF32_BE
;
133 if (len
>= 3 && ptr
[0] == '\xBB' && ptr
[1] == '\xBF') {
139 if (*ptr
== '\xFF') {
140 *bom
= GIT_BOM_UTF16_BE
;
147 if (len
>= 4 && ptr
[1] == 0 && ptr
[2] == 0) {
148 *bom
= GIT_BOM_UTF32_LE
;
151 *bom
= GIT_BOM_UTF16_LE
;
162 bool git_buf_text_gather_stats(
163 git_buf_text_stats
*stats
, const git_buf
*buf
, bool skip_bom
)
165 const char *scan
= buf
->ptr
, *end
= buf
->ptr
+ buf
->size
;
168 memset(stats
, 0, sizeof(*stats
));
171 skip
= git_buf_text_detect_bom(&stats
->bom
, buf
, 0);
175 /* Ignore EOF character */
176 if (buf
->size
> 0 && end
[-1] == '\032')
181 unsigned char c
= *scan
++;
183 if ((c
> 0x1F && c
< 0x7F) || c
> 0x9f)
188 stats
->nonprintable
++;
195 if (scan
< end
&& *scan
== '\n')
198 case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/
202 stats
->nonprintable
++;
207 return (stats
->nul
> 0 ||
208 ((stats
->printable
>> 7) < stats
->nonprintable
));