📄 subst.c
字号:
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_REVISION_MEDIUM,
(sizeof (SVN_KEYWORD_REVISION_MEDIUM)) - 1,
expand ? keywords->revision : NULL))
return TRUE;
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_REVISION_SHORT,
(sizeof (SVN_KEYWORD_REVISION_SHORT)) - 1,
expand ? keywords->revision : NULL))
return TRUE;
}
/* Date */
if (keywords->date)
{
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_DATE_LONG,
(sizeof (SVN_KEYWORD_DATE_LONG)) - 1,
expand ? keywords->date : NULL))
return TRUE;
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_DATE_SHORT,
(sizeof (SVN_KEYWORD_DATE_SHORT)) - 1,
expand ? keywords->date : NULL))
return TRUE;
}
/* Author */
if (keywords->author)
{
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_AUTHOR_LONG,
(sizeof (SVN_KEYWORD_AUTHOR_LONG)) - 1,
expand ? keywords->author : NULL))
return TRUE;
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_AUTHOR_SHORT,
(sizeof (SVN_KEYWORD_AUTHOR_SHORT)) - 1,
expand ? keywords->author : NULL))
return TRUE;
}
/* URL */
if (keywords->url)
{
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_URL_LONG,
(sizeof (SVN_KEYWORD_URL_LONG)) - 1,
expand ? keywords->url : NULL))
return TRUE;
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_URL_SHORT,
(sizeof (SVN_KEYWORD_URL_SHORT)) - 1,
expand ? keywords->url : NULL))
return TRUE;
}
/* Id */
if (keywords->id)
{
if (translate_keyword_subst (buf, len,
SVN_KEYWORD_ID,
(sizeof (SVN_KEYWORD_ID)) - 1,
expand ? keywords->id : NULL))
return TRUE;
}
/* No translations were successful. Return FALSE. */
return FALSE;
}
/* Translate NEWLINE_BUF (length of NEWLINE_LEN) to the newline format
specified in EOL_STR (length of EOL_STR_LEN), and write the
translated thing to FILE (whose path is DST_PATH).
SRC_FORMAT (length *SRC_FORMAT_LEN) is a cache of the first newline
found while processing SRC_PATH. If the current newline is not the
same style as that of SRC_FORMAT, look to the REPAIR parameter. If
REPAIR is TRUE, ignore the inconsistency, else return an
SVN_ERR_IO_INCONSISTENT_EOL error. If we are examining the first
newline in the file, copy it to {SRC_FORMAT, *SRC_FORMAT_LEN} to
use for later consistency checks.
Use POOL to allocate errors that may occur. */
static svn_error_t *
translate_newline (const char *eol_str,
apr_size_t eol_str_len,
char *src_format,
apr_size_t *src_format_len,
char *newline_buf,
apr_size_t newline_len,
svn_stream_t *dst,
svn_boolean_t repair)
{
/* If this is the first newline we've seen, cache it
future comparisons, else compare it with our cache to
check for consistency. */
if (*src_format_len)
{
/* Comparing with cache. If we are inconsistent and
we are NOT repairing the file, generate an error! */
if ((! repair) &&
((*src_format_len != newline_len) ||
(strncmp (src_format, newline_buf, newline_len))))
return svn_error_create (SVN_ERR_IO_INCONSISTENT_EOL, NULL, NULL);
}
else
{
/* This is our first line ending, so cache it before
handling it. */
strncpy (src_format, newline_buf, newline_len);
*src_format_len = newline_len;
}
/* Translate the newline */
return translate_write (dst, eol_str, eol_str_len);
}
/*** Public interfaces. ***/
svn_boolean_t
svn_subst_keywords_differ (const svn_subst_keywords_t *a,
const svn_subst_keywords_t *b,
svn_boolean_t compare_values)
{
if (((a == NULL) && (b == NULL)) /* no A or B */
/* no A, and B has no contents */
|| ((a == NULL)
&& (b->revision == NULL)
&& (b->date == NULL)
&& (b->author == NULL)
&& (b->url == NULL))
/* no B, and A has no contents */
|| ((b == NULL) && (a->revision == NULL)
&& (a->date == NULL)
&& (a->author == NULL)
&& (a->url == NULL))
/* neither A nor B has any contents */
|| ((a != NULL) && (b != NULL)
&& (b->revision == NULL)
&& (b->date == NULL)
&& (b->author == NULL)
&& (b->url == NULL)
&& (a->revision == NULL)
&& (a->date == NULL)
&& (a->author == NULL)
&& (a->url == NULL)))
{
return FALSE;
}
else if ((a == NULL) || (b == NULL))
return TRUE;
/* Else both A and B have some keywords. */
if ((! a->revision) != (! b->revision))
return TRUE;
else if ((compare_values && (a->revision != NULL))
&& (strcmp (a->revision->data, b->revision->data) != 0))
return TRUE;
if ((! a->date) != (! b->date))
return TRUE;
else if ((compare_values && (a->date != NULL))
&& (strcmp (a->date->data, b->date->data) != 0))
return TRUE;
if ((! a->author) != (! b->author))
return TRUE;
else if ((compare_values && (a->author != NULL))
&& (strcmp (a->author->data, b->author->data) != 0))
return TRUE;
if ((! a->url) != (! b->url))
return TRUE;
else if ((compare_values && (a->url != NULL))
&& (strcmp (a->url->data, b->url->data) != 0))
return TRUE;
/* Else we never found a difference, so they must be the same. */
return FALSE;
}
svn_error_t *
svn_subst_translate_stream (svn_stream_t *s, /* src stream */
svn_stream_t *d, /* dst stream */
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
svn_boolean_t expand)
{
char buf[SVN_STREAM_CHUNK_SIZE + 1];
const char *p, *interesting;
apr_size_t len, readlen;
apr_size_t eol_str_len = eol_str ? strlen (eol_str) : 0;
char newline_buf[2] = { 0 };
apr_size_t newline_off = 0;
char keyword_buf[SVN_KEYWORD_MAX_LEN] = { 0 };
apr_size_t keyword_off = 0;
char src_format[2] = { 0 };
apr_size_t src_format_len = 0;
/* The docstring requires that *some* translation be requested. */
assert (eol_str || keywords);
interesting = (eol_str && keywords) ? "$\r\n" : eol_str ? "\r\n" : "$";
readlen = sizeof (buf) - 1;
while (readlen == sizeof (buf) - 1)
{
SVN_ERR (svn_stream_read (s, buf, &readlen));
buf[readlen] = '\0';
/* At the beginning of this loop, assume that we might be in an
* interesting state, i.e. with data in the newline or keyword
* buffer. First try to get to the boring state so we can copy
* a run of boring characters; then try to get back to the
* interesting state by processing an interesting character,
* and repeat. */
for (p = buf; p < buf + readlen;)
{
/* Try to get to the boring state, if necessary. */
if (newline_off)
{
if (*p == '\n')
newline_buf[newline_off++] = *p++;
SVN_ERR (translate_newline (eol_str, eol_str_len, src_format,
&src_format_len, newline_buf,
newline_off, d, repair));
newline_off = 0;
}
else if (keyword_off && *p == '$')
{
/* If translation fails, treat this '$' as a starting '$'. */
keyword_buf[keyword_off++] = '$';
if (translate_keyword (keyword_buf, &keyword_off, expand,
keywords))
p++;
else
keyword_off--;
SVN_ERR (translate_write (d, keyword_buf, keyword_off));
keyword_off = 0;
}
else if (keyword_off == SVN_KEYWORD_MAX_LEN - 1
|| (keyword_off && (*p == '\r' || *p == '\n')))
{
/* No closing '$' found; flush the keyword buffer. */
SVN_ERR (translate_write (d, keyword_buf, keyword_off));
keyword_off = 0;
}
else if (keyword_off)
{
keyword_buf[keyword_off++] = *p++;
continue;
}
/* We're in the boring state; look for interest characters.
* For lack of a memcspn(), manually skip past NULs. */
len = 0;
while (1)
{
len += strcspn (p + len, interesting);
if (p[len] != '\0' || p + len == buf + readlen)
break;
len++;
}
if (len)
SVN_ERR (translate_write (d, p, len));
p += len;
/* Set up state according to the interesting character, if any. */
switch (*p)
{
case '$':
keyword_buf[keyword_off++] = *p++;
break;
case '\r':
newline_buf[newline_off++] = *p++;
break;
case '\n':
newline_buf[newline_off++] = *p++;
SVN_ERR (translate_newline (eol_str, eol_str_len, src_format,
&src_format_len, newline_buf,
newline_off, d, repair));
newline_off = 0;
break;
}
}
}
if (newline_off)
SVN_ERR (translate_newline (eol_str, eol_str_len, src_format,
&src_format_len, newline_buf, newline_off, d,
repair));
if (keyword_off)
SVN_ERR (translate_write (d, keyword_buf, keyword_off));
return SVN_NO_ERROR;
}
svn_error_t *
svn_subst_translate_cstring (const char *src,
const char **dst,
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
svn_boolean_t expand,
apr_pool_t *pool)
{
svn_stringbuf_t *src_stringbuf, *dst_stringbuf;
svn_stream_t *src_stream, *dst_stream;
svn_error_t *err;
src_stringbuf = svn_stringbuf_create (src, pool);
/* The easy way out: no translation needed, just copy. */
if (! (eol_str || keywords))
{
dst_stringbuf = svn_stringbuf_dup (src_stringbuf, pool);
goto all_good;
}
/* Convert our stringbufs into streams. */
src_stream = svn_stream_from_stringbuf (src_stringbuf, pool);
dst_stringbuf = svn_stringbuf_create ("", pool);
dst_stream = svn_stream_from_stringbuf (dst_stringbuf, pool);
/* Translate src stream into dst stream. */
err = svn_subst_translate_stream (src_stream, dst_stream,
eol_str, repair, keywords, expand);
if (err)
{
svn_error_clear (svn_stream_close (src_stream));
svn_error_clear (svn_stream_close (dst_stream));
return err;
}
/* clean up nicely. */
SVN_ERR (svn_stream_close (src_stream));
SVN_ERR (svn_stream_close (dst_stream));
all_good:
*dst = dst_stringbuf->data;
return SVN_NO_ERROR;
}
svn_error_t *
svn_subst_copy_and_translate (const char *src,
const char *dst,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -