/* ==================================================================== * 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 #include // svn #include 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(v); } static DiffToken* dt_cast( void* v ) { return static_cast(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(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