   *
     * However!  @a offset + @a length may be *beyond* the end of the existing
     * target data.  "Where the heck does the text come from, then?"
     * If you start at @a offset, and append @a length bytes one at a time,
     * it'll work out --- you're adding new bytes to the end at the
     * same rate you're reading them from the middle.  Thus, if your
     * current target text is "abcdefgh", and you get an #svn_txdelta_target
     * instruction whose @a offset is 6 and whose @a length is 7,
     * the resulting string is "abcdefghghghghg".  This trick is actually
     * useful in encoding long runs of consecutive characters, long runs
     * of CR/LF pairs, etc.
     */
    svn_txdelta_target,

    /** Append the @a length bytes at @a offset in the window's @a new string
     * to the target.
     *
     * It must be the case that 0 <= @a offset < @a offset +
     * @a length <= length of @a new.  Windows MUST use new data in ascending
     * order with no overlap at the moment; svn_txdelta_to_svndiff()
     * depends on this.
     */
    svn_txdelta_new
};

/** A single text delta instruction.  */
typedef struct svn_txdelta_op_t
{
  /** Action code of delta instruction */
  enum svn_delta_action action_code;
  /** Offset of delta, see #svn_delta_action for more details. */
  apr_size_t offset;
   /** Number of bytes of delta, see #svn_delta_action for more details. */
  apr_size_t length;
} svn_txdelta_op_t;


/** An #svn_txdelta_window_t object describes how to reconstruct a
 * contiguous section of the target string (the "target view") using a
 * specified contiguous region of the source string (the "source
 * view").  It contains a series of instructions which assemble the
 * new target string text by pulling together substrings from:
 *
 *   - the source view,
 *
 *   - the previously constructed portion of the target view,
 *
 *   - a string of new data contained within the window structure
 *
 * The source view must always slide forward from one window to the
 * next; that is, neither the beginning nor the end of the source view
 * may move to the left as we read from a window stream.  This
 * property allows us to apply deltas to non-seekable source streams
 * without making a full copy of the source stream.
 */
typedef struct svn_txdelta_window_t
{

  /** The offset of the source view for this window.  */
  svn_filesize_t sview_offset;

  /** The length of the source view for this window.  */
  apr_size_t sview_len;

  /** The length of the target view for this window, i.e. the number of
   * bytes which will be reconstructed by the instruction stream.  */
  apr_size_t tview_len;

  /** The number of instructions in this window.  */
  int num_ops;

  /** The number of svn_txdelta_source instructions in this window. If
   * this number is 0, we don't need to read the source in order to
   * reconstruct the target view.
   */
  int src_ops;

  /** The instructions for this window.  */
  const svn_txdelta_op_t *ops;

  /** New data, for use by any `svn_txdelta_new' instructions.  */
  const svn_string_t *new_data;

} svn_txdelta_window_t;

/**
 * Return a deep copy of @a window, allocated in @a pool.
 *
 * @since New in 1.3.
 */
svn_txdelta_window_t *
svn_txdelta_window_dup(const svn_txdelta_window_t *window,
                       apr_pool_t *pool);

/**
 * Compose two delta windows, yielding a third, allocated in @a pool.
 *
 * @since New in 1.4
 *
 */
svn_txdelta_window_t *
svn_txdelta_compose_windows(const svn_txdelta_window_t *window_A,
                            const svn_txdelta_window_t *window_B,
                            apr_pool_t *pool);

/**
 * Apply the instructions from @a window to a source view @a sbuf to
 *  produce a target view @a tbuf.
 *
 * @a sbuf is assumed to have @a window->sview_len bytes of data and
 * @a tbuf is assumed to have room for @a tlen bytes of output.  @a
 * tlen may be more than @a window->tview_len, so return the actual
 * number of bytes written.  @a sbuf is not touched and may be NULL if
 * @a window contains no source-copy operations. This is purely a
 * memory operation; nothing can go wrong as long as we have a valid
 * window.
 *
 * @since New in 1.4
 *
 * @since Since 1.9, @a tbuf may be NULL if @a *tlen is 0.
 */
void
svn_txdelta_apply_instructions(svn_txdelta_window_t *window,
                               const char *sbuf, char *tbuf,
                               apr_size_t *tlen);

/** A typedef for functions that consume a series of delta windows, for
 * use in caller-pushes interfaces.  Such functions will typically
 * apply the delta windows to produce some file, or save the windows
 * somewhere.  At the end of the delta window stream, you must call
 * this function passing zero for the @a window argument.
 */
typedef svn_error_t *(*svn_txdelta_window_handler_t)(
  svn_txdelta_window_t *window, void *baton);


/** This function will generate delta windows that turn @a source into
 * @a target, and pushing these windows into the @a handler window handler
 * callback (passing @a handler_baton to each invocation).
 *
 * If @a checksum is not NULL, then a checksum (of kind @a checksum_kind)
 * will be computed for the target stream, and placed into *checksum.
 *
 * If @a cancel_func is not NULL, then it should refer to a cancellation
 * function (along with @a cancel_baton).
 *
 * Results (the checksum) will be allocated from @a result_pool, and all
 * temporary allocations will be performed in @a scratch_pool.
 *
 * Note: this function replaces the combination of svn_txdelta() and
 *   svn_txdelta_send_txstream().
 *
 * @since New in 1.6.
 */
svn_error_t *
svn_txdelta_run(svn_stream_t *source,
                svn_stream_t *target,
                svn_txdelta_window_handler_t handler,
                void *handler_baton,
                svn_checksum_kind_t checksum_kind,
                svn_checksum_t **checksum,
                svn_cancel_func_t cancel_func,
                void *cancel_baton,
                apr_pool_t *result_pool,
                apr_pool_t *scratch_pool);


/** A delta stream --- this is the hat from which we pull a series of
 * svn_txdelta_window_t objects, which, taken in order, describe the
 * entire target string.  This type is defined within libsvn_delta, and
 * opaque outside that library.
 */
typedef struct svn_txdelta_stream_t svn_txdelta_stream_t;


/** A typedef for a function that will set @a *window to the next
 * window from a #svn_txdelta_stream_t object.  If there are no more
 * delta windows, NULL will be used.  The returned window, if any,
 * will be allocated in @a pool.  @a baton is the baton specified
 * when the stream was created.
 *
 * @since New in 1.4.
 */
typedef svn_error_t *
(*svn_txdelta_next_window_fn_t)(svn_txdelta_window_t **window,
                                void *baton,
                                apr_pool_t *pool);

/** A typedef for a function that will return the md5 checksum of the
 * fulltext deltified by a #svn_txdelta_stream_t object.  Will
 * return NULL if the final null window hasn't yet been returned by
 * the stream.  The returned value will be allocated in the same pool
 * as the stream.  @a baton is the baton specified when the stream was
 * created.
 *
 * @since New in 1.4.
 */
typedef const unsigned char *
(*svn_txdelta_md5_digest_fn_t)(void *baton);

/** A typedef for a function that opens an #svn_txdelta_stream_t object,
 * allocated in @a result_pool.  @a baton is provided by the caller.
 * Any temporary allocations may be performed in @a scratch_pool.
 *
 * @since New in 1.10.
 */
typedef svn_error_t *
(*svn_txdelta_stream_open_func_t)(svn_txdelta_stream_t **txdelta_stream,
                                  void *baton,
                                  apr_pool_t *result_pool,
                                  apr_pool_t *scratch_pool);

/** Create and return a generic text delta stream with @a baton, @a
 * next_window and @a md5_digest.  Allocate the new stream in @a
 * pool.
 *
 * @since New in 1.4.
 */
svn_txdelta_stream_t *
svn_txdelta_stream_create(void *baton,
                          svn_txdelta_next_window_fn_t next_window,
                          svn_txdelta_md5_digest_fn_t md5_digest,
                          apr_pool_t *pool);

/** Set @a *window to a pointer to the next window from the delta stream
 * @a stream.  When we have completely reconstructed the target string,
 * set @a *window to zero.
 *
 * The window will be allocated in @a pool.
 */
svn_error_t *
svn_txdelta_next_window(svn_txdelta_window_t **window,
                        svn_txdelta_stream_t *stream,
                        apr_pool_t *pool);


/** Return the md5 digest for the complete fulltext deltified by
 * @a stream, or @c NULL if @a stream has not yet returned its final
 * @c NULL window.  The digest is allocated in the same memory as @a
 * STREAM.
 */
const unsigned char *
svn_txdelta_md5_digest(svn_txdelta_stream_t *stream);

/** Set @a *stream to a pointer to a delta stream that will turn the byte
 * string from @a source into the byte stream from @a target.
 *
 * @a source and @a target are both readable generic streams.  When we call
 * svn_txdelta_next_window() on @a *stream, it will read from @a source and
 * @a target to gather as much data as it needs.  If @a calculate_checksum
 * is set, you may call svn_txdelta_md5_digest() to get an MD5 checksum
 * for @a target.
 *
 * Do any necessary allocation in a sub-pool of @a pool.
 *
 * @since New in 1.8.
 */
void
svn_txdelta2(svn_txdelta_stream_t **stream,
             svn_stream_t *source,
             svn_stream_t *target,
             svn_boolean_t calculate_checksum,
             apr_pool_t *pool);

/** Similar to svn_txdelta2 but always calculating the target checksum.
 *
 * @deprecated Provided for backward compatibility with the 1.7 API.
 */
SVN_DEPRECATED
void
svn_txdelta(svn_txdelta_stream_t **stream,
            svn_stream_t *source,
            svn_stream_t *target,
            apr_pool_t *pool);


/**
 * Return a writable stream which, when fed target data, will send
 * delta windows to @a handler/@a handler_baton which transform the
 * data in @a source to the target data.  As usual, the window handler
 * will receive a NULL window to signify the end of the window stream.
 * The stream handler functions will read data from @a source as
 * necessary.
 *
 * @since New in 1.1.
 */
svn_stream_t *
svn_txdelta_target_push(svn_txdelta_window_handler_t handler,
                        void *handler_baton,
                        svn_stream_t *source,
                        apr_pool_t *pool);


/** Send the contents of @a string to window-handler @a handler/@a baton.
 * This is effectively a 'copy' operation, resulting in delta windows that
 * make the target equivalent to the value of @a string.
 *
 * All temporary allocation is performed in @a pool.
 */
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);

/** Send the contents of @a stream to window-handler @a handler/@a baton.
 * This is effectively a 'copy' operation, resulting in delta windows that
 * make the target equivalent to the stream.
 *
 * If @a digest is non-NULL, populate it with the md5 checksum for the
 * fulltext that was deltified (@a digest must be at least
 * @c APR_MD5_DIGESTSIZE bytes long).
 *
 * All temporary allocation is performed in @a pool.
 */
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);

/** Send the contents of @a txstream to window-handler @a handler/@a baton.
 * Windows will be extracted from the stream and delivered to the handler.
 *
 * All temporary allocation is performed in @a pool.
 */
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);


/** Send the @a contents of length @a len as a txdelta against an empty
 * source directly to window-handler @a handler/@a handler_baton.
 *
 * All temporary allocation is performed in @a pool.
 *
 * @since New in 1.8.
 */
svn_error_t *
svn_txdelta_send_contents(const unsigned char *contents,
                          apr_size_t len,
                          svn_txdelta_window_handler_t handler,
                          void *handler_baton,
                          apr_pool_t *pool);

/** Prepare to apply a text delta.  @a source is a readable generic stream
 * yielding the source data, @a target is a writable generic stream to
 * write target data to, and allocation takes place in a sub-pool of
 * @a pool.  On return, @a *handler is set to a window handler function and
 * @a *handler_baton is set to the value to pass as the @a baton argument to
 * @a *handler.
 *
 * If @a result_digest is non-NULL, it points to APR_MD5_DIGESTSIZE bytes
 * of storage, and the final call to @a handler populates it with the
 * MD5 digest of the resulting fulltext.
 *
 * If @a error_info is non-NULL, it is inserted parenthetically into
 * the error string for any error returned by svn_txdelta_apply() or
 * @a *handler.  (It is normally used to provide path information,
 * since there's nothing else in the delta application's context to
 * supply a path for error messages.)
 *
 * The @a source stream will NOT be closed. The @a target stream will be
 * closed when the window handler is given a null window to signal the
 * end of the delta.
 *
 * @note To avoid lifetime issues, @a error_info is copied into
 * @a pool or a subpool thereof.
 */
void
svn_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);


