⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subst.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * have the same life time as that of POOL. * */static struct translation_baton *create_translation_baton(const char *eol_str,                         svn_boolean_t repair,                         apr_hash_t *keywords,                         svn_boolean_t expand,                         apr_pool_t *pool){  struct translation_baton *b = apr_palloc(pool, sizeof(*b));  /* For efficiency, convert an empty set of keywords to NULL. */  if (keywords && (apr_hash_count(keywords) == 0))    keywords = NULL;  b->eol_str = eol_str;  b->eol_str_len = eol_str ? strlen(eol_str) : 0;  b->repair = repair;  b->keywords = keywords;  b->expand = expand;  b->interesting = (eol_str && keywords) ? "$\r\n" : eol_str ? "\r\n" : "$";  b->newline_off = 0;  b->keyword_off = 0;  b->src_format_len = 0;  return b;}/* Translate eols and keywords of a 'chunk' of characters BUF of size BUFLEN * according to the settings and state stored in baton B. * * Write output to stream DST. * * To finish a series of chunk translations, flush all buffers by calling * this routine with a NULL value for BUF. * * Use POOL for temporary allocations. */static svn_error_t *translate_chunk(svn_stream_t *dst,                struct translation_baton *b,                const char *buf,                apr_size_t buflen,                apr_pool_t *pool){  const char *p;  apr_size_t len;  if (buf)    {      /* precalculate some oft-used values */      const char *end = buf + buflen;      const char *interesting = b->interesting;      apr_size_t next_sign_off = 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 < end;)        {          /* Try to get to the boring state, if necessary. */          if (b->newline_off)            {              if (*p == '\n')                b->newline_buf[b->newline_off++] = *p++;              SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,                                        b->src_format,                                        &b->src_format_len, b->newline_buf,                                        b->newline_off, dst, b->repair));              b->newline_off = 0;            }          else if (b->keyword_off && *p == '$')            {              svn_boolean_t keyword_matches;              char keyword_name[SVN_KEYWORD_MAX_LEN + 1];              /* If keyword is matched, but not correctly translated, try to               * look for the next ending '$'. */              b->keyword_buf[b->keyword_off++] = *p++;              keyword_matches = match_keyword(b->keyword_buf, b->keyword_off,                                              keyword_name, b->keywords);              if (keyword_matches == FALSE)                {                  /* reuse the ending '$' */                  p--;                  b->keyword_off--;                }              if (keyword_matches == FALSE ||                  translate_keyword(b->keyword_buf, &b->keyword_off,                                    keyword_name, b->expand, b->keywords) ||                  b->keyword_off >= SVN_KEYWORD_MAX_LEN)                {                  /* write out non-matching text or translated keyword */                  SVN_ERR(translate_write(dst, b->keyword_buf, b->keyword_off));                  next_sign_off = 0;                  b->keyword_off = 0;                }              else                {                  if (next_sign_off == 0)                    next_sign_off = b->keyword_off - 1;                  continue;                }            }          else if (b->keyword_off == SVN_KEYWORD_MAX_LEN - 1                   || (b->keyword_off && (*p == '\r' || *p == '\n')))            {              if (next_sign_off > 0)              {                /* rolling back, continue with next '$' in keyword_buf */                p -= (b->keyword_off - next_sign_off);                b->keyword_off = next_sign_off;                next_sign_off = 0;              }              /* No closing '$' found; flush the keyword buffer. */              SVN_ERR(translate_write(dst, b->keyword_buf, b->keyword_off));              b->keyword_off = 0;            }          else if (b->keyword_off)            {              b->keyword_buf[b->keyword_off++] = *p++;              continue;            }          /* We're in the boring state; look for interest characters. */          len = 0;          /* We wanted memcspn(), but lacking that, the loop below has             the same effect.             Also, skip NUL characters explicitly, since strchr()             considers them part of the string argument,             but we don't consider them interesting          */          while ((p + len) < end                 && (! p[len] || ! strchr(interesting, p[len])))            len++;          if (len)            SVN_ERR(translate_write(dst, p, len));          p += len;          /* Set up state according to the interesting character, if any. */          if (p < end)            {              switch (*p)                {                case '$':                  b->keyword_buf[b->keyword_off++] = *p++;                  break;                case '\r':                  b->newline_buf[b->newline_off++] = *p++;                  break;                case '\n':                  b->newline_buf[b->newline_off++] = *p++;                  SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,                                            b->src_format,                                            &b->src_format_len,                                            b->newline_buf,                                            b->newline_off, dst, b->repair));                  b->newline_off = 0;                  break;                }            }        }    }  else    {      if (b->newline_off)        {          SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,                                    b->src_format, &b->src_format_len,                                    b->newline_buf, b->newline_off,                                    dst, b->repair));          b->newline_off = 0;        }      if (b->keyword_off)        {          SVN_ERR(translate_write(dst, b->keyword_buf, b->keyword_off));          b->keyword_off = 0;        }    }  return SVN_NO_ERROR;}/* Baton for use with translated stream callbacks. */struct translated_stream_baton{  /* Stream to take input from (before translation) on read     /write output to (after translation) on write. */  svn_stream_t *stream;  /* Input/Output translation batons to make them separate chunk streams. */  struct translation_baton *in_baton, *out_baton;  /* Remembers whether any write operations have taken place;     if so, we need to flush the output chunk stream. */  svn_boolean_t written;  /* Buffer to hold translated read data. */  svn_stringbuf_t *readbuf;  /* Offset of the first non-read character in readbuf. */  apr_size_t readbuf_off;  /* Buffer to hold read data     between svn_stream_read() and translate_chunk(). */  char *buf;  /* Pool in which (only!) this baton is allocated. */  apr_pool_t *pool;  /* Pool for callback iterations */  apr_pool_t *iterpool;};static svn_error_t *translated_stream_read(void *baton,                       char *buffer,                       apr_size_t *len){  struct translated_stream_baton *b = baton;  apr_size_t readlen = SVN__STREAM_CHUNK_SIZE;  apr_size_t unsatisfied = *len;  apr_size_t off = 0;  apr_pool_t *iterpool;  iterpool = b->iterpool;  while (readlen == SVN__STREAM_CHUNK_SIZE && unsatisfied > 0)    {      apr_size_t to_copy;      apr_size_t buffer_remainder;      svn_pool_clear(iterpool);      /* fill read buffer, if necessary */      if (! (b->readbuf_off < b->readbuf->len))        {          svn_stream_t *buf_stream;          svn_stringbuf_setempty(b->readbuf);          b->readbuf_off = 0;          SVN_ERR(svn_stream_read(b->stream, b->buf, &readlen));          buf_stream = svn_stream_from_stringbuf(b->readbuf, iterpool);          SVN_ERR(translate_chunk(buf_stream, b->in_baton, b->buf,                                  readlen, iterpool));          if (readlen != SVN__STREAM_CHUNK_SIZE)            SVN_ERR(translate_chunk(buf_stream, b->in_baton, NULL, 0,                                    iterpool));          SVN_ERR(svn_stream_close(buf_stream));        }      /* Satisfy from the read buffer */      buffer_remainder = b->readbuf->len - b->readbuf_off;      to_copy = (buffer_remainder > unsatisfied)        ? unsatisfied : buffer_remainder;      memcpy(buffer + off, b->readbuf->data + b->readbuf_off, to_copy);      off += to_copy;      b->readbuf_off += to_copy;      unsatisfied -= to_copy;    }  *len -= unsatisfied;  return SVN_NO_ERROR;}static svn_error_t *translated_stream_write(void *baton,                        const char *buffer,                        apr_size_t *len){  struct translated_stream_baton *b = baton;  svn_pool_clear(b->iterpool);  b->written = TRUE;  SVN_ERR(translate_chunk(b->stream, b->out_baton, buffer, *len,                          b->iterpool));  return SVN_NO_ERROR;}static svn_error_t *translated_stream_close(void *baton){  struct translated_stream_baton *b = baton;  if (b->written)    SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool));  SVN_ERR(svn_stream_close(b->stream));  svn_pool_destroy(b->pool);   /* Also destroys the baton itself */  return SVN_NO_ERROR;}/* Given a special file at SRC, set TRANSLATED_STREAM_P to a stream   with the textual representation of it. Perform all allocations in POOL. */static svn_error_t *detranslated_stream_special(svn_stream_t **translated_stream_p,                            const char *src,                            apr_pool_t *pool){  apr_finfo_t finfo;  apr_file_t *s;  svn_string_t *buf;  svn_stringbuf_t *strbuf;    /* First determine what type of special file we are     detranslating. */  SVN_ERR(svn_io_stat(&finfo, src, APR_FINFO_MIN | APR_FINFO_LINK, pool));    switch (finfo.filetype) {  case APR_REG:    /* Nothing special to do here, just create stream from the original       file's contents. */    SVN_ERR(svn_io_file_open(&s, src, APR_READ | APR_BUFFERED,                             APR_OS_DEFAULT, pool));    *translated_stream_p = svn_stream_from_aprfile2(s, FALSE, pool);    break;  case APR_LNK:    /* Determine the destination of the link. */    SVN_ERR(svn_io_read_link(&buf, src, pool));    strbuf = svn_stringbuf_createf(pool, "link %s", buf->data);    *translated_stream_p = svn_stream_from_stringbuf(strbuf, pool);        break;  default:    abort();  }    return SVN_NO_ERROR;}svn_error_t *svn_subst_stream_detranslated(svn_stream_t **stream_p,                               const char *src,                              svn_subst_eol_style_t eol_style,                              const char *eol_str,                              svn_boolean_t always_repair_eols,                              apr_hash_t *keywords,                              svn_boolean_t special,                              apr_pool_t *pool){  apr_file_t *file_h;  svn_stream_t *src_stream;  if (special)    return detranslated_stream_special(stream_p, src, pool);    if (eol_style == svn_subst_eol_style_native)    eol_str = SVN_SUBST__DEFAULT_EOL_STR;  else if (! (eol_style == svn_subst_eol_style_fixed              || eol_style == svn_subst_eol_style_none))    return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);  SVN_ERR(svn_io_file_open(&file_h, src, APR_READ,                           APR_OS_DEFAULT, pool));  src_stream = svn_stream_from_aprfile2(file_h, FALSE, pool);  *stream_p = svn_subst_stream_translated(    src_stream, eol_str,    eol_style == svn_subst_eol_style_fixed || always_repair_eols,    keywords, FALSE, pool);  return SVN_NO_ERROR;}svn_stream_t *svn_subst_stream_translated(svn_stream_t *stream,                            const char *eol_str,                            svn_boolean_t repair,                            apr_hash_t *keywords,                            svn_boolean_t expand,                            apr_pool_t *pool){  apr_pool_t *baton_pool = svn_pool_create(pool);  struct translated_stream_baton *baton    = apr_palloc(baton_pool, sizeof(*baton));  svn_stream_t *s = svn_stream_create(baton, baton_pool);  /* Make sure EOL_STR and KEYWORDS are allocated in POOL, as     required by create_translation_baton() */  if (eol_str)    eol_str = apr_pstrdup(baton_pool, eol_str);  if (keywords)    {      if (apr_hash_count(keywords) == 0)        keywords = NULL;      else        {          /* deep copy the hash to make sure it's allocated in POOL */          apr_hash_t *copy = apr_hash_make(baton_pool);          apr_hash_index_t *hi;          for (hi = apr_hash_first(pool, keywords);               hi; hi = apr_hash_next(hi))            {              const void *key;              void *val;              apr_hash_this(hi, &key, NULL, &val);              apr_hash_set(copy, apr_pstrdup(baton_pool, key),                           APR_HASH_KEY_STRING,                           svn_string_dup(val, baton_pool));            }          keywords = copy;        }    }  /* Setup the baton fields */  baton->stream = stream;  baton->in_baton    = create_translation_baton(eol_str, repair, keywords, expand, baton_pool);  baton->out_baton    = create_translation_baton(eol_str, repair, keywords, expand, baton_pool);  baton->written = FALSE;  baton->readbuf = svn_stringbuf_create("", baton_pool);  baton->readbuf_off = 0;  baton->iterpool = svn_pool_create(baton_pool);  baton->pool = baton_pool;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -