Skip to content

Commit

Permalink
Fixed potential segmentation fault with --header usage
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpreynolds committed Jun 18, 2017
2 parents 9cab495 + 95f6bbf commit 42ed6f5
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 73 deletions.
35 changes: 0 additions & 35 deletions applications/bed/bedops/doc/Usage.Statement.Version1.2

This file was deleted.

65 changes: 59 additions & 6 deletions applications/bed/bedops/src/Bedops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ struct GetType {
typedef typename NoPtr<typename BedFiles::value_type>::Type::BedType BedType;

/*
A c++ priority queue return the greatest element first. This is done, by default
A c++ priority queue returns the greatest element first. This is done, by default
using std::less<>. If you want the least element, you have to use std::greater<>.
In our case, the analogs are Bed::GenomicAddressCompare for std::less<> (max element
first), and Bed::InvertGenomicAddressCompare for std::greater<> (min element first).
Expand All @@ -212,6 +212,20 @@ struct GetType {
BedType*, std::vector<BedType*>,
Bed::GenomicAddressCompare<BedType, BedType>
> PQ;

template <typename BedType>
struct InvertedBedWithFileIdx : public Bed::InvertGenomicRestAddressCompare<BedType, BedType> {
typedef Bed::InvertGenomicRestAddressCompare<BedType, BedType> Base;
inline bool operator()(std::pair<BedType*, int>& p1, std::pair<BedType*, int>& p2) {
return Base::operator()(p1.first, p2.first);
}
};

// use when BedType has full_rest() and you need to keep track of which file it came from
typedef std::priority_queue<
std::pair<BedType*, int>, std::vector<std::pair<BedType*, int>>,
InvertedBedWithFileIdx<BedType>
> IPQ_Rest;
};

//=============
Expand Down Expand Up @@ -796,9 +810,9 @@ void doSymmetricDifference(BedFiles& bedFiles) {
Remove(toRecord);
}

//==============
// doUnionAll()
//==============
//=================================
// doUnionAll() and doUnionAllPQ()
//=================================
template <typename BedFiles>
typename std::enable_if<GetType<BedFiles>::BedType::UseRest, typename GetType<BedFiles>::BedType>::type*
nextUnionAllLine(BedFiles&); /* requires BedType::UseRest to be true */
Expand Down Expand Up @@ -835,6 +849,41 @@ void doUnionAll(BedFiles& bedFiles) {
} // while
}

template <typename BedFiles>
void doUnionAllPQ(BedFiles& bedFiles) {
/* meant for cases with large numbers of input files (50+ maybe) */
/* If inputs have duplicate entries, output will too */
typedef typename GetType<BedFiles>::BedType BedType;
typename GetType<BedFiles>::IPQ_Rest pq; // union uses full_rest()
static BedType* const zero = static_cast<BedType*>(0);

BedType* r = zero;
if ( 1 == bedFiles.size() ) {
/* a simple cat command, possibly post-padded as
dealt with in BedPadReader. */
while ( bedFiles[0]->HasNext() ) {
r = bedFiles[0]->ReadLine();
record(r);
bedFiles[0]->Remove(r);
} // while
return;
}

for ( int i = 0; i < bedFiles.size(); ++i ) {
if ( bedFiles[i]->HasNext() )
pq.push(std::make_pair(bedFiles[i]->ReadLine(), i));
} // for

while ( !pq.empty() ) {
const std::pair<BedType*, int> val = pq.top();
pq.pop();
record(val.first);
bedFiles[val.second]->Remove(val.first);
if ( bedFiles[val.second]->HasNext() )
pq.push(std::make_pair(bedFiles[val.second]->ReadLine(), val.second));
} // while
}

//===========================
// getNextFileMergedCoords()
//===========================
Expand Down Expand Up @@ -1600,8 +1649,12 @@ void selectWork(const Input& input, BedFiles& bedFiles) {
doSymmetricDifference(bedFiles);
break;
case UNIONALL:
if ( GetType<BedFiles>::BedType::UseRest )
doUnionAll(bedFiles);
if ( GetType<BedFiles>::BedType::UseRest ) {
if ( bedFiles.size() < 10 )
doUnionAll(bedFiles);
else
doUnionAllPQ(bedFiles);
} // else linker will fail
break;
default:
throw(Ext::ProgramError("Unsupported mode"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ namespace Bed {

template <class BedType, std::size_t SZ=Bed::CHUNKSZ>
class allocate_iterator_starch_bed;

template <class BedType, std::size_t SZ>
class allocate_iterator_starch_bed<BedType*, SZ> {

public:
typedef std::forward_iterator_tag iterator_category;
typedef BedType* value_type;
Expand Down
71 changes: 41 additions & 30 deletions interfaces/general-headers/data/bed/BedCompare.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace Bed {
struct GenomicAddressCompare
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
inline bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
static int v = 0;
if ( (v = std::strcmp(ptr1->chrom(), ptr2->chrom())) != 0 )
return v < 0;
Expand All @@ -67,7 +67,7 @@ namespace Bed {
struct InvertGenomicAddressCompare
: private GenomicAddressCompare<BedType1, BedType2> {
typedef GenomicAddressCompare<BedType1, BedType2> Base;
bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
inline bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
return Base::operator()(ptr2, ptr1);
}
};
Expand All @@ -76,7 +76,7 @@ namespace Bed {
struct CoordCompare // ignoring chrom here
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
return one->end() < two->end();
Expand All @@ -87,7 +87,7 @@ namespace Bed {
struct CoordAddressCompare // not caring about chrom here
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
if ( one->end() != two->end() )
Expand All @@ -101,7 +101,7 @@ namespace Bed {
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<T::UseRest && U::UseRest, bool>::type
inline typename std::enable_if<T::UseRest && U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -111,7 +111,7 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<T::UseRest && !U::UseRest, bool>::type
inline typename std::enable_if<T::UseRest && !U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -121,7 +121,7 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<!T::UseRest && U::UseRest, bool>::type
inline typename std::enable_if<!T::UseRest && U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -131,15 +131,15 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<!T::UseRest && !U::UseRest && T::NumFields == 3 && U::NumFields == 3, bool>::type
inline typename std::enable_if<!T::UseRest && !U::UseRest && T::NumFields == 3 && U::NumFields == 3, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
return one->end() < two->end();
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<!T::UseRest && !U::UseRest && (T::NumFields != 3 || U::NumFields != 3), bool>::type
inline typename std::enable_if<!T::UseRest && !U::UseRest && (T::NumFields != 3 || U::NumFields != 3), bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -165,7 +165,7 @@ namespace Bed {
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<T::UseRest && U::UseRest, bool>::type
inline typename std::enable_if<T::UseRest && U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -178,7 +178,7 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<T::UseRest && !U::UseRest, bool>::type
inline typename std::enable_if<T::UseRest && !U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -191,7 +191,7 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<!T::UseRest && U::UseRest, bool>::type
inline typename std::enable_if<!T::UseRest && U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
Expand All @@ -204,7 +204,7 @@ namespace Bed {
}

template <typename T=BedType1, typename U=BedType2>
typename std::enable_if<!T::UseRest && !U::UseRest, bool>::type
inline typename std::enable_if<!T::UseRest && !U::UseRest, bool>::type
operator()(BedType1 const* one, BedType2 const* two) const {
static CoordRestCompare<T, U> crc; // deals with ID fields and such
bool check = crc(one, two);
Expand All @@ -217,11 +217,30 @@ namespace Bed {
}
};

template <typename BedType1, typename BedType2 = BedType1>
struct GenomicRestAddressCompare : CoordRestAddressCompare<BedType1, BedType2> {
typedef CoordRestAddressCompare<BedType1, BedType2> BaseT;
inline bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
static int v = 0;
if ( (v = std::strcmp(ptr1->chrom(), ptr2->chrom())) != 0 )
return v < 0;
return BaseT::operator()(ptr1, ptr2);
}
};

template <typename BedType1, typename BedType2 = BedType1>
struct InvertGenomicRestAddressCompare
: private GenomicRestAddressCompare<BedType1, BedType2> {
typedef GenomicRestAddressCompare<BedType1, BedType2> Base;
inline bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
return Base::operator()(ptr2, ptr1);
}
};

template <typename BedType1, typename BedType2 = BedType1>
struct RevCoordAddressCompare // not caring about chrom here
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->end() != two->end() )
return one->end() < two->end();
if ( one->start() != two->start() )
Expand All @@ -233,8 +252,7 @@ namespace Bed {
template <typename BedType1, typename BedType2 = BedType1>
struct EndCoordAddressCompareLesser
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->end() != two->end() )
return one->end() < two->end();
return one < two;
Expand All @@ -244,8 +262,7 @@ namespace Bed {
template <typename BedType1, typename BedType2 = BedType1>
struct EndCoordAddressCompareGreater
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->end() != two->end() )
return one->end() > two->end();
return one > two;
Expand All @@ -255,8 +272,7 @@ namespace Bed {
template <typename BedType1, typename BedType2 = BedType1>
struct StartCoordAddressCompareLesser
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() < two->start();
return one < two;
Expand All @@ -266,8 +282,7 @@ namespace Bed {
template <typename BedType1, typename BedType2 = BedType1>
struct StartCoordAddressCompareGreater
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->start() != two->start() )
return one->start() > two->start();
return one > two;
Expand All @@ -277,18 +292,15 @@ namespace Bed {
template <typename BedType1, typename BedType2 = BedType1>
struct ScoreCompare
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
return one->measurement() < two->measurement();
}
};

template <typename BedType1, typename BedType2 = BedType1>
struct ScoreThenGenomicCompareLesser
: public std::binary_function<BedType1 const*, BedType2 const*, bool> {

inline
bool operator()(BedType1 const* one, BedType2 const* two) const {
inline bool operator()(BedType1 const* one, BedType2 const* two) const {
if ( one->measurement() != two->measurement() )
return one->measurement() < two->measurement();

Expand All @@ -305,8 +317,7 @@ namespace Bed {
struct ScoreThenGenomicCompareGreater
: private ScoreThenGenomicCompareLesser<BedType1, BedType2> {
typedef ScoreThenGenomicCompareLesser<BedType1, BedType2> Base;
inline
bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
inline bool operator()(BedType1 const* ptr1, BedType2 const* ptr2) const {
return Base::operator()(ptr2, ptr1);
}
};
Expand Down

0 comments on commit 42ed6f5

Please sign in to comment.