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

📄 text_delta.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
{  struct tpush_baton *tb = baton;  apr_size_t chunk_len, data_len = *len;  apr_pool_t *pool = svn_pool_create(tb->pool);  svn_txdelta_window_t *window;  while (data_len > 0)    {      svn_pool_clear(pool);      /* Make sure we're all full up on source data, if possible. */      if (tb->source_len == 0 && !tb->source_done)        {          tb->source_len = SVN_DELTA_WINDOW_SIZE;          SVN_ERR(svn_stream_read(tb->source, tb->buf, &tb->source_len));          if (tb->source_len < SVN_DELTA_WINDOW_SIZE)            tb->source_done = TRUE;        }      /* Copy in the target data, up to SVN_DELTA_WINDOW_SIZE. */      chunk_len = SVN_DELTA_WINDOW_SIZE - tb->target_len;      if (chunk_len > data_len)        chunk_len = data_len;      memcpy(tb->buf + tb->source_len + tb->target_len, data, chunk_len);      data += chunk_len;      data_len -= chunk_len;      tb->target_len += chunk_len;      /* If we're full of target data, compute and fire off a window. */      if (tb->target_len == SVN_DELTA_WINDOW_SIZE)        {          window = compute_window(tb->buf, tb->source_len, tb->target_len,                                  tb->source_offset, pool);          SVN_ERR(tb->wh(window, tb->whb));          tb->source_offset += tb->source_len;          tb->source_len = 0;          tb->target_len = 0;        }    }  svn_pool_destroy(pool);  return SVN_NO_ERROR;}/* This is the close handler for a target-push delta stream.  It sends * a final window if there is any buffered target data, and then sends * a NULL window signifying the end of the window stream. */static svn_error_t *tpush_close_handler(void *baton){  struct tpush_baton *tb = baton;  svn_txdelta_window_t *window;  /* Send a final window if we have any residual target data. */  if (tb->target_len > 0)    {      window = compute_window(tb->buf, tb->source_len, tb->target_len,                              tb->source_offset, tb->pool);      SVN_ERR(tb->wh(window, tb->whb));    }  /* Send a final NULL window signifying the end. */  SVN_ERR(tb->wh(NULL, tb->whb));  return SVN_NO_ERROR;}svn_stream_t *svn_txdelta_target_push(svn_txdelta_window_handler_t handler,                        void *handler_baton, svn_stream_t *source,                        apr_pool_t *pool){  struct tpush_baton *tb;  svn_stream_t *stream;  /* Initialize baton. */  tb = apr_palloc(pool, sizeof(*tb));  tb->source = source;  tb->wh = handler;  tb->whb = handler_baton;  tb->pool = pool;  tb->buf = apr_palloc(pool, 2 * SVN_DELTA_WINDOW_SIZE);  tb->source_offset = 0;  tb->source_len = 0;  tb->source_done = FALSE;  tb->target_len = 0;  /* Create and return writable stream. */  stream = svn_stream_create(tb, pool);  svn_stream_set_write(stream, tpush_write_handler);  svn_stream_set_close(stream, tpush_close_handler);  return stream;}/* Functions for applying deltas.  *//* Ensure that BUF has enough space for VIEW_LEN bytes.  */static APR_INLINE voidsize_buffer(char **buf, apr_size_t *buf_size,            apr_size_t view_len, apr_pool_t *pool){  if (view_len > *buf_size)    {      *buf_size *= 2;      if (*buf_size < view_len)        *buf_size = view_len;      *buf = apr_palloc(pool, *buf_size);    }}voidsvn_txdelta_apply_instructions(svn_txdelta_window_t *window,                               const char *sbuf, char *tbuf,                               apr_size_t *tlen){  const svn_txdelta_op_t *op;  apr_size_t i, j, tpos = 0;  for (op = window->ops; op < window->ops + window->num_ops; op++)    {      const apr_size_t buf_len = (op->length < *tlen - tpos                                  ? op->length : *tlen - tpos);      /* Check some invariants common to all instructions.  */      assert(tpos + op->length <= window->tview_len);      switch (op->action_code)        {        case svn_txdelta_source:          /* Copy from source area.  */          assert(op->offset + op->length <= window->sview_len);          memcpy(tbuf + tpos, sbuf + op->offset, buf_len);          break;        case svn_txdelta_target:          /* Copy from target area.  Don't use memcpy() since its             semantics aren't guaranteed for overlapping memory areas,             and target copies are allowed to overlap to generate             repeated data.  */          assert(op->offset < tpos);          for (i = op->offset, j = tpos; i < op->offset + buf_len; i++)            tbuf[j++] = tbuf[i];          break;        case svn_txdelta_new:          /* Copy from window new area.  */          assert(op->offset + op->length <= window->new_data->len);          memcpy(tbuf + tpos,                 window->new_data->data + op->offset,                 buf_len);          break;        default:          assert(!"Invalid delta instruction code");        }      tpos += op->length;      if (tpos >= *tlen)        return;                 /* The buffer is full. */    }  /* Check that we produced the right amount of data.  */  assert(tpos == window->tview_len);  *tlen = tpos;}/* This is a private interlibrary compatibility wrapper. */voidsvn_txdelta__apply_instructions(svn_txdelta_window_t *window,                                const char *sbuf, char *tbuf,                                apr_size_t *tlen);voidsvn_txdelta__apply_instructions(svn_txdelta_window_t *window,                                const char *sbuf, char *tbuf,                                apr_size_t *tlen){  svn_txdelta_apply_instructions(window, sbuf, tbuf, tlen);}/* Apply WINDOW to the streams given by APPL.  */static svn_error_t *apply_window(svn_txdelta_window_t *window, void *baton){  struct apply_baton *ab = (struct apply_baton *) baton;  apr_size_t len;  svn_error_t *err;  if (window == NULL)    {      /* We're done; just clean up.  */      if (ab->result_digest)        apr_md5_final(ab->result_digest, &(ab->md5_context));      err = svn_stream_close(ab->target);      svn_pool_destroy(ab->pool);      return err;    }  /* Make sure the source view didn't slide backwards.  */  assert(window->sview_len == 0         || (window->sview_offset >= ab->sbuf_offset             && (window->sview_offset + window->sview_len                 >= ab->sbuf_offset + ab->sbuf_len)));  /* Make sure there's enough room in the target buffer.  */  size_buffer(&ab->tbuf, &ab->tbuf_size, window->tview_len, ab->pool);  /* Prepare the source buffer for reading from the input stream.  */  if (window->sview_offset != ab->sbuf_offset      || window->sview_len > ab->sbuf_size)    {      char *old_sbuf = ab->sbuf;      /* Make sure there's enough room.  */      size_buffer(&ab->sbuf, &ab->sbuf_size, window->sview_len, ab->pool);      /* If the existing view overlaps with the new view, copy the       * overlap to the beginning of the new buffer.  */      if (ab->sbuf_offset + ab->sbuf_len > window->sview_offset)        {          apr_size_t start =            (apr_size_t)(window->sview_offset - ab->sbuf_offset);          memmove(ab->sbuf, old_sbuf + start, ab->sbuf_len - start);          ab->sbuf_len -= start;        }      else        ab->sbuf_len = 0;      ab->sbuf_offset = window->sview_offset;    }  /* Read the remainder of the source view into the buffer.  */  if (ab->sbuf_len < window->sview_len)    {      len = window->sview_len - ab->sbuf_len;      err = svn_stream_read(ab->source, ab->sbuf + ab->sbuf_len, &len);      if (err == SVN_NO_ERROR && len != window->sview_len - ab->sbuf_len)        err = svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,                               "Delta source ended unexpectedly");      if (err != SVN_NO_ERROR)        return err;      ab->sbuf_len = window->sview_len;    }  /* Apply the window instructions to the source view to generate     the target view.  */  len = window->tview_len;  svn_txdelta_apply_instructions(window, ab->sbuf, ab->tbuf, &len);  assert(len == window->tview_len);  /* Write out the output. */  /* ### We've also considered just adding two (optionally null)     arguments to svn_stream_create(): read_checksum and     write_checksum.  Then instead of every caller updating an md5     context when it calls svn_stream_write() or svn_stream_read(),     streams would do it automatically, and verify the checksum in     svn_stream_closed().  But this might be overkill for issue #689;     so for now we just update the context here. */  if (ab->result_digest)    apr_md5_update(&(ab->md5_context), ab->tbuf, len);  return svn_stream_write(ab->target, ab->tbuf, &len);}voidsvn_txdelta_apply(svn_stream_t *source,                  svn_stream_t *target,                  unsigned char *result_digest,                  const char *error_info,                  apr_pool_t *pool,                  svn_txdelta_window_handler_t *handler,                  void **handler_baton){  apr_pool_t *subpool = svn_pool_create(pool);  struct apply_baton *ab;  ab = apr_palloc(subpool, sizeof(*ab));  ab->source = source;  ab->target = target;  ab->pool = subpool;  ab->sbuf = NULL;  ab->sbuf_size = 0;  ab->sbuf_offset = 0;  ab->sbuf_len = 0;  ab->tbuf = NULL;  ab->tbuf_size = 0;  ab->result_digest = result_digest;  if (result_digest)    apr_md5_init(&(ab->md5_context));  if (error_info)    ab->error_info = apr_pstrdup(subpool, error_info);  else    ab->error_info = NULL;  *handler = apply_window;  *handler_baton = ab;}/* Convenience routines */svn_error_t * svn_txdelta_send_string(const svn_string_t *string,                        svn_txdelta_window_handler_t handler,                        void *handler_baton,                        apr_pool_t *pool){  svn_txdelta_window_t window = { 0 };  svn_txdelta_op_t op;  /* Build a single `new' op */  op.action_code = svn_txdelta_new;  op.offset = 0;  op.length = string->len;  /* Build a single window containing a ptr to the string. */  window.tview_len = string->len;  window.num_ops = 1;  window.ops = &op;  window.new_data = string;  /* Push the one window at the handler. */  SVN_ERR((*handler)(&window, handler_baton));    /* Push a NULL at the handler, because we're done. */  SVN_ERR((*handler)(NULL, handler_baton));    return SVN_NO_ERROR;}svn_error_t *svn_txdelta_send_stream(svn_stream_t *stream,                                     svn_txdelta_window_handler_t handler,                                     void *handler_baton,                                     unsigned char *digest,                                     apr_pool_t *pool){  svn_txdelta_stream_t *txstream;  svn_error_t *err;  /* ### this is a hack. we should simply read from the stream, construct     ### some windows, and pass those to the handler. there isn't any reason     ### to crank up a full "diff" algorithm just to copy a stream.     ###     ### will fix RSN. */  /* Create a delta stream which converts an *empty* bytestream into the     target bytestream. */  svn_txdelta(&txstream, svn_stream_empty(pool), stream, pool);  err = svn_txdelta_send_txstream(txstream, handler, handler_baton, pool);  if (digest && (! err))    {      const unsigned char *result_md5;      result_md5 = svn_txdelta_md5_digest(txstream);      /* Since err is null, result_md5 "cannot" be null. */      memcpy(digest, result_md5, APR_MD5_DIGESTSIZE);    }  return err;}svn_error_t *svn_txdelta_send_txstream(svn_txdelta_stream_t *txstream,                                       svn_txdelta_window_handler_t handler,                                       void *handler_baton,                                       apr_pool_t *pool){  svn_txdelta_window_t *window;  /* create a pool just for the windows */  apr_pool_t *wpool = svn_pool_create(pool);  do    {      /* free the window (if any) */      svn_pool_clear(wpool);      /* read in a single delta window */      SVN_ERR(svn_txdelta_next_window(&window, txstream, wpool));      /* shove it at the handler */      SVN_ERR((*handler)(window, handler_baton));    }  while (window != NULL);  svn_pool_destroy(wpool);  return SVN_NO_ERROR;}

⌨️ 快捷键说明

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