rgc, char *argv[]) {
             printf("Hello World!\n");
     } @endverbatim
 *
 * And the modified text is:
 *
 * @verbatim
     #include <stdio.h>
     int main(int argc, char *argv[]) {
             printf("I like Subversion!\n");
     } @endverbatim
 *
 * @see svn_diff_hunk_readline_diff_text()
 * @see svn_diff_hunk_readline_original_text()
 * @see svn_diff_hunk_readline_modified_text()
 *
 * @since New in 1.7. */
typedef struct svn_diff_hunk_t svn_diff_hunk_t;

/**
 * Allocate @a *stringbuf in @a result_pool, and read into it one line
 * of the diff text of @a hunk. The hunk header is not returned only the
 * unidiff data lines (starting with '+', '-', or ' ') are returned.
 * If the @a hunk is being interpreted in reverse (i.e. the reverse
 * parameter of svn_diff_parse_next_patch() was @c TRUE), the diff
 * text will be returned in reversed form.
 * The line-terminator is detected automatically and stored in @a *eol
 * if @a eol is not NULL.
 * If EOF is reached, set @a *eof to TRUE, and set @a *eol to NULL if the
 * hunk does not end with a newline character and @a eol is not NULL.
 * Temporary allocations will be performed in @a scratch_pool.
 *
 * @note The hunk header information can be retrieved with the following
 * functions:
 * @see svn_diff_hunk_get_original_start()
 * @see svn_diff_hunk_get_original_length()
 * @see svn_diff_hunk_get_modified_start()
 * @see svn_diff_hunk_get_modified_length()
 *
 * @since New in 1.7.
 */
svn_error_t *
svn_diff_hunk_readline_diff_text(svn_diff_hunk_t *hunk,
                                 svn_stringbuf_t **stringbuf,
                                 const char **eol,
                                 svn_boolean_t *eof,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool);

/**
 * Allocate @a *stringbuf in @a result_pool, and read into it one line
 * of the original text of @a hunk.
 * The line-terminator is detected automatically and stored in @a *eol
 * if @a eol is not NULL.
 * If EOF is reached, set @a *eof to TRUE, and set @a *eol to NULL if the
 * hunk text does not end with a newline character and @a eol is not NULL.
 * Temporary allocations will be performed in @a scratch_pool.
 *
 * @see svn_diff_hunk_t
 * @since New in 1.7.
 */
svn_error_t *
svn_diff_hunk_readline_original_text(svn_diff_hunk_t *hunk,
                                     svn_stringbuf_t **stringbuf,
                                     const char **eol,
                                     svn_boolean_t *eof,
                                     apr_pool_t *result_pool,
                                     apr_pool_t *scratch_pool);

/**
 * Like svn_diff_hunk_readline_original_text(), but it returns lines from
 * the modified text of the hunk.
 *
 * @see svn_diff_hunk_t
 * @since New in 1.7.
 */
svn_error_t *
svn_diff_hunk_readline_modified_text(svn_diff_hunk_t *hunk,
                                     svn_stringbuf_t **stringbuf,
                                     const char **eol,
                                     svn_boolean_t *eof,
                                     apr_pool_t *result_pool,
                                     apr_pool_t *scratch_pool);

/** Reset the diff text of @a hunk so it can be read again from the start.
 * @since New in 1.7. */
void
svn_diff_hunk_reset_diff_text(svn_diff_hunk_t *hunk);

/** Reset the original text of @a hunk so it can be read again from the start.
 * @since New in 1.7. */
void
svn_diff_hunk_reset_original_text(svn_diff_hunk_t *hunk);

/** Reset the modified text of @a hunk so it can be read again from the start.
 * @since New in 1.7. */
void
svn_diff_hunk_reset_modified_text(svn_diff_hunk_t *hunk);

/** Return the line offset of the original hunk text,
 * as parsed from the hunk header.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_original_start(const svn_diff_hunk_t *hunk);

/** Return the number of lines in the original @a hunk text,
 * as parsed from the hunk header.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_original_length(const svn_diff_hunk_t *hunk);

/** Return the line offset of the modified @a hunk text,
 * as parsed from the hunk header.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_modified_start(const svn_diff_hunk_t *hunk);

/** Return the number of lines in the modified @a hunk text,
 * as parsed from the hunk header.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_modified_length(const svn_diff_hunk_t *hunk);

/** Return the number of lines of leading context of @a hunk,
 * i.e. the number of lines starting with ' ' before the first line
 * that starts with a '+' or '-'.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_leading_context(const svn_diff_hunk_t *hunk);

/** Return the number of lines of trailing context of @a hunk,
 * i.e. the number of lines starting with ' ' after the last line
 * that starts with a '+' or '-'.
 * @since New in 1.7. */
svn_linenum_t
svn_diff_hunk_get_trailing_context(const svn_diff_hunk_t *hunk);

/**
 * Data type to manage parsing of properties in patches.
 * API users should not allocate structures of this type directly.
 *
 * @since New in 1.7. */
typedef struct svn_prop_patch_t {
  const char *name;

  /** Represents the operation performed on the property */
  svn_diff_operation_kind_t operation;

  /**
   * An array containing an svn_diff_hunk_t object for each hunk parsed
   * from the patch associated with our property name */
  apr_array_header_t *hunks;
} svn_prop_patch_t;

/**
 * A binary patch representation. This basically describes replacing one
 * exact binary representation with another one.
 *
 * @since New in 1.10. */
typedef struct svn_diff_binary_patch_t svn_diff_binary_patch_t;

/**
 * Creates a stream allocated in @a result_pool from which the original
 * (pre-patch-application) version of the binary patched file can be read.
 *
 * @note Like many svn_diff_get functions over patches, this is implemented
 * as reading from the backing patch file. Therefore it is recommended to
 * read the whole stream before using other functions on the same patch file.
 *
 * @since New in 1.10 */
svn_stream_t *
svn_diff_get_binary_diff_original_stream(const svn_diff_binary_patch_t *bpatch,
                                         apr_pool_t *result_pool);

/**
 * Creates a stream allocated in @a result_pool from which the resulting
 * (post-patch-application) version of the binary patched file can be read.
 *
 * @note Like many svn_diff_get functions over patches, this is implemented
 * as reading from the backing patch file. Therefore it is recommended to
 * read the whole stream before using other functions on the same patch file.
 *
 * @since New in 1.10 */
svn_stream_t *
svn_diff_get_binary_diff_result_stream(const svn_diff_binary_patch_t *bpatch,
                                       apr_pool_t *result_pool);

/**
 * Data type to manage parsing of patches.
 *
 * Represents a patch to one target file.
 *
 * API users should not allocate structures of this type directly.
 *
 * @since New in 1.7. */
typedef struct svn_patch_t {
  /**
   * The old and new file names as retrieved from the patch file.
   * These paths are UTF-8 encoded and canonicalized, but otherwise
   * left unchanged from how they appeared in the patch file. */
  const char *old_filename;
  const char *new_filename;

  /**
   * An array containing an svn_diff_hunk_t * for each hunk parsed
   * from the patch. */
  apr_array_header_t *hunks;

  /**
   * A hash table keyed by property names containing svn_prop_patch_t
   * object for each property parsed from the patch. */
  apr_hash_t *prop_patches;

  /**
   * Represents the operation performed on the file. */
  svn_diff_operation_kind_t operation;

  /**
   * Indicates whether the patch is being interpreted in reverse.
   * ### If so, how does this affect the interpretation of other fields?
   */
  svn_boolean_t reverse;

  /**
   * Mergeinfo parsed from svn:mergeinfo diff data, with one entry for
   * forward merges and one for reverse merges.
   * Either entry can be @c NULL if no such merges are part of the diff.
   * @since New in 1.9. */
  svn_mergeinfo_t mergeinfo;
  svn_mergeinfo_t reverse_mergeinfo;

  /**
   * Declares that there is a binary conflict and contains the information
   * to apply it as parsed from the file.
   * @since New in 1.10. */
  svn_diff_binary_patch_t *binary_patch;

  /** The old and new executability bits, as retrieved from the patch file, from
   * the git-like mode headers.
   *
   * A patch may specify an executability change via @a old_executable_bit and
   * @a new_executable_bit, via a #SVN_PROP_EXECUTABLE propchange hunk, or both
   * ways. It is upto caller how to decide how conflicting information is
   * handled.
   *
   * #svn_tristate_unknown indicates the patch does not specify the
   * corresponding bit.
   *
   * @since New in 1.10.
   */
  svn_tristate_t old_executable_bit;
  svn_tristate_t new_executable_bit;

  /** The old and new symlink bits, as retrieved from the patch file, from
  * the git-like mode headers.
  *
  * A patch may specify a symlink change via @a old_symlink_bit and
  * @a new_symlink_bit, via a #SVN_PROP_SPECIAL propchange hunk, or both
  * ways. It is upto caller how to decide how conflicting information is
  * handled. Most implementations will currently just describe a replacement
  * of the file though.
  *
  * #svn_tristate_unknown indicates the patch does not specify the
  * corresponding bit.
  *
  * @since New in 1.10.
  */
  svn_tristate_t old_symlink_bit;
  svn_tristate_t new_symlink_bit;
} svn_patch_t;

/** An opaque type representing an open patch file.
 *
 * @since New in 1.7. */
typedef struct svn_patch_file_t svn_patch_file_t;

/** Open @a patch_file at @a local_abspath.
 * Allocate @a patch_file in @a result_pool.
 *
 * @since New in 1.7. */
svn_error_t *
svn_diff_open_patch_file(svn_patch_file_t **patch_file,
                         const char *local_abspath,
                         apr_pool_t *result_pool);

/**
 * Return the next @a *patch in @a patch_file.
 * If no patch can be found, set @a *patch to NULL.
 * If @a reverse is TRUE, invert the patch while parsing it.
 * If @a ignore_whitespace is TRUE, allow patches with no leading
 * whitespace to be parsed.
 * Allocate results in @a result_pool.
 * Use @a scratch_pool for all other allocations.
 *
 * @since New in 1.7. */
svn_error_t *
svn_diff_parse_next_patch(svn_patch_t **patch,
                          svn_patch_file_t *patch_file,
                          svn_boolean_t reverse,
                          svn_boolean_t ignore_whitespace,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);

/**
 * Dispose of @a patch_file.
 * Use @a scratch_pool for all temporary allocations.
 *
 * @since New in 1.7.
 */
svn_error_t *
svn_diff_close_patch_file(svn_patch_file_t *patch_file,
                          apr_pool_t *scratch_pool);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* SVN_DIFF_H */
