/* ====================================================================
* Copyright (c) 2003-2006, Martin Hauner
* http://subcommander.tigris.org
*
* Subcommander is licensed as described in the file doc/COPYING, which
* you should have received as part of this distribution.
* ====================================================================
*/
// sc
#include "Diff.h"
#include "Error.h"
#include "util/AprException.h"
// apr
#include <apr_errno.h>
#include <apr_pools.h>
// svn
#include <svn_diff.h>
namespace svn
{
class DiffFns
{
public:
DiffFns( DiffBaton* baton )
: _baton(baton)
{
}
DiffBaton* getBaton() const
{
return _baton;
}
svn_diff_fns_t* getFns() const
{
return &_fns;
}
static Diff::DataSource getDataSource( svn_diff_datasource_e ds )
{
switch( ds )
{
case svn_diff_datasource_original:
return Diff::srcOriginal;
case svn_diff_datasource_modified:
return Diff::srcModified;
case svn_diff_datasource_latest:
return Diff::srcLatest;
case svn_diff_datasource_ancestor:
return Diff::srcAncestor;
}
// TODO, not apr
throw apr::Exception( 0, sc::String("unknown svn_diff_datasource_x") );
}
static DiffFns* df_cast( void* v )
{
return static_cast<DiffFns*>(v);
}
static DiffToken* dt_cast( void* v )
{
return static_cast<DiffToken*>(v);
}
static svn_error_t* datasource_open( void *diff_baton, svn_diff_datasource_e datasource )
{
DiffFns* fns = df_cast(diff_baton);
sc::Error* err = fns->getBaton()->open( getDataSource(datasource) );
return unwrapError(err);
}
static svn_error_t* datasource_close( void *diff_baton, svn_diff_datasource_e datasource )
{
DiffFns* fns = df_cast(diff_baton);
sc::Error* err = fns->getBaton()->close( getDataSource(datasource) );
return unwrapError(err);
}
static svn_error_t* datasource_get_next_token( apr_uint32_t *hash, void **token, void *diff_baton, svn_diff_datasource_e datasource )
{
DiffFns* fns = df_cast(diff_baton);
DiffToken* diffToken = NULL;
sc::Error* err = fns->getBaton()->getNextToken( &diffToken, getDataSource(datasource) );
*token = diffToken;
return unwrapError(err);
}
static svn_error_t* token_compare( void *diff_baton, void *ltoken, void *rtoken, int* compare )
{
DiffFns* fns = df_cast(diff_baton);
*compare = fns->getBaton()->compareToken( dt_cast(ltoken), dt_cast(rtoken) );
return SVN_NO_ERROR;
}
#if 0
static int token_compare( void *diff_baton, void *ltoken, void *rtoken )
{
DiffFns* fns = df_cast(diff_baton);
return fns->getBaton()->compareToken( dt_cast(ltoken), dt_cast(rtoken) );
}
#endif
static void token_discard( void *diff_baton, void *token )
{
DiffFns* fns = df_cast(diff_baton);
fns->getBaton()->discardToken( dt_cast(token) );
}
static void token_discard_all(void *diff_baton)
{
DiffFns* fns = df_cast(diff_baton);
fns->getBaton()->discardAllToken();
}
private:
static svn_diff_fns_t _fns;
DiffBaton* _baton;
};
svn_diff_fns_t DiffFns::_fns =
{
datasource_open,
datasource_close,
datasource_get_next_token,
token_compare,
token_discard,
token_discard_all
};
//
///////////////////////////////////////////////////////////////////////////////
//
Diff::Diff( apr_pool_t* pool )
{
apr_status_t status = apr_pool_create( &_pool, pool );
if( status != APR_SUCCESS )
{
throw apr::Exception(status, sc::String("failed to create pool") );
}
}
Diff::~Diff()
{
apr_pool_destroy(_pool);
}
sc::Error* Diff::diff( DiffData** diff, DiffBaton* baton )
{
svn_error_t* svn_error = NULL;
svn_diff_t* svn_diff = NULL;
DiffFns fns(baton);
svn_error = svn_diff_diff( &svn_diff, &fns, fns.getFns(), _pool );
*diff = new DiffData(svn_diff);
return wrapError(svn_error);
}
sc::Error* Diff::diff3( DiffData** diff, DiffBaton* baton )
{
svn_error_t* svn_error = NULL;
svn_diff_t* svn_diff = NULL;
DiffFns fns(baton);
svn_error = svn_diff_diff3( &svn_diff, &fns, fns.getFns(), _pool );
*diff = new DiffData(svn_diff);
return wrapError(svn_error);
}
sc::Error* Diff::diff4( DiffData** diff, DiffBaton* baton )
{
svn_error_t* svn_error = NULL;
svn_diff_t* svn_diff = NULL;
DiffFns fns(baton);
svn_error = svn_diff_diff4( &svn_diff, &fns, fns.getFns(), _pool );
*diff = new DiffData(svn_diff);
return wrapError(svn_error);
}
//
///////////////////////////////////////////////////////////////////////////////
//
DiffOffsets::DiffOffsets()
: _originalStart(0), _originalLength(0),
_modifiedStart(0), _modifiedLength(0),
_latestStart(0), _latestLength(0)
{
}
DiffOffsets::DiffOffsets(
Offset oS, Offset oL,
Offset mS, Offset mL,
Offset lS, Offset lL )
: _originalStart(oS), _originalLength(oL),
_modifiedStart(mS), _modifiedLength(mL),
_latestStart(lS), _latestLength(lL)
{
}
class OutputFns
{
public:
OutputFns( OutputBaton* baton )
: _baton(baton)
{
}
OutputBaton* getBaton() const
{
return _baton;
}
svn_diff_output_fns_t* getFns() const
{
return &_fns;
}
static OutputFns* of_cast( void* v )
{
return static_cast<OutputFns*>(v);
}
static svn_error_t* output_common( void *output_baton,
apr_off_t original_start, apr_off_t original_length,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length )
{
OutputFns* fns = of_cast(output_baton);
DiffOffsets offs(
original_start, original_length,
modified_start, modified_length,
latest_start, latest_length );
sc::Error* err = fns->getBaton()->common( offs );
return unwrapError(err);
}
static svn_error_t* output_diff_modified( void *output_baton,
apr_off_t original_start, apr_off_t original_length,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length )
{
OutputFns* fns = of_cast(output_baton);
DiffOffsets offs(
original_start, original_length,
modified_start, modified_length,
latest_start, latest_length );
sc::Error* err = fns->getBaton()->diffModified( offs );
return unwrapError(err);
}
static svn_error_t* output_diff_latest( void *output_baton,
apr_off_t original_start, apr_off_t original_length,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length )
{
OutputFns* fns = of_cast(output_baton);
DiffOffsets offs(
original_start, original_length,
modified_start, modified_length,
latest_start, latest_length );
sc::Error* err = fns->getBaton()->diffLatest( offs );
return unwrapError(err);
}
static svn_error_t* output_diff_common( void *output_baton,
apr_off_t original_start, apr_off_t original_length,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length )
{
OutputFns* fns = of_cast(output_baton);
DiffOffsets offs(
original_start, original_length,
modified_start, modified_length,
latest_start, latest_length );
sc::Error* err = fns->getBaton()->diffCommon( offs );
return unwrapError(err);
}
static svn_error_t* output_conflict( void *output_baton,
apr_off_t original_start, apr_off_t original_length,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length,
svn_diff_t *resolved_diff )
{
OutputFns* fns = of_cast(output_baton);
// TODO!?!?
DiffData data(resolved_diff);
DiffOffsets offs(
original_start, original_length,
modified_start, modified_length,
latest_start, latest_length );
sc::Error* err = fns->getBaton()->conflict( offs, &data );
return unwrapError(err);
}
private:
static svn_diff_output_fns_t _fns;
OutputBaton* _baton;
};
svn_diff_output_fns_t OutputFns::_fns =
{
output_common,
output_diff_modified,
output_diff_latest,
output_diff_common,
output_conflict
};
//
///////////////////////////////////////////////////////////////////////////////
//
DiffData::DiffData(svn_diff_t* diff) : _diff(diff)
{
}
DiffData::~DiffData()
{
}
sc::Error* DiffData::output( OutputBaton* baton )
{
svn_error_t* svn_error = NULL;
OutputFns fns(baton);
svn_error = svn_diff_output( _diff, &fns, fns.getFns() );
return wrapError(svn_error);
}
bool DiffData::hasConflicts() const
{
return svn_diff_contains_conflicts(_diff) == TRUE;
}
bool DiffData::hasDifferences() const
{
return svn_diff_contains_diffs(_diff) == TRUE;
}
//
///////////////////////////////////////////////////////////////////////////////
} // namespace
syntax highlighted by Code2HTML, v. 0.9.1