]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamMultiMerger_p.h
9248df0eb39a6dca3d2ca99e8b08e5f6b7315259
[bamtools.git] / src / api / internal / BamMultiMerger_p.h
1 // ***************************************************************************
2 // BamMultiMerger_p.h (c) 2010 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 3 October 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides merging functionality for BamMultiReader.  At this point, supports
8 // sorting results by (refId, position) or by read name.
9 // ***************************************************************************
10
11 #ifndef BAMMULTIMERGER_P_H
12 #define BAMMULTIMERGER_P_H
13
14 //  -------------
15 //  W A R N I N G
16 //  -------------
17 //
18 // This file is not part of the BamTools API.  It exists purely as an
19 // implementation detail. This header file may change from version to version
20 // without notice, or even be removed.
21 //
22 // We mean it.
23
24 #include <api/BamAlignment.h>
25 #include <api/BamReader.h>
26 #include <api/algorithms/Sort.h>
27 #include <deque>
28 #include <functional>
29 #include <set>
30 #include <string>
31
32 namespace BamTools {
33 namespace Internal {
34
35 struct MergeItem {
36
37     // data members
38     BamReader*    Reader;
39     BamAlignment* Alignment;
40
41     // ctors & dtor
42     MergeItem(BamReader* reader = 0,
43               BamAlignment* alignment = 0)
44         : Reader(reader)
45         , Alignment(alignment)
46     { }
47
48     MergeItem(const MergeItem& other)
49         : Reader(other.Reader)
50         , Alignment(other.Alignment)
51     { }
52
53     ~MergeItem(void) { }
54 };
55
56 template<typename Compare>
57 struct MergeItemSorter : public std::binary_function<MergeItem, MergeItem, bool> {
58
59     public:
60         MergeItemSorter(const Compare& comp = Compare())
61             : m_comp(comp)
62         { }
63
64         bool operator()(const MergeItem& lhs, const MergeItem& rhs) {
65             const BamAlignment& l = *lhs.Alignment;
66             const BamAlignment& r = *rhs.Alignment;
67             return m_comp(l,r);
68         }
69
70     private:
71         Compare m_comp;
72 };
73
74 // pure ABC so we can just work polymorphically with any specific merger implementation
75 class IMultiMerger {
76
77     public:
78         IMultiMerger(void) { }
79         virtual ~IMultiMerger(void) { }
80     public:
81         virtual void Add(MergeItem item) =0;
82         virtual void Clear(void) =0;
83         virtual const MergeItem& First(void) const =0;
84         virtual bool IsEmpty(void) const =0;
85         virtual void Remove(BamReader* reader) =0;
86         virtual int Size(void) const =0;
87         virtual MergeItem TakeFirst(void) =0;
88 };
89
90 // general merger
91 template<typename Compare>
92 class MultiMerger : public IMultiMerger {
93
94     public:
95         typedef Compare                      CompareType;
96         typedef MergeItemSorter<CompareType> MergeType;
97
98     public:
99         explicit MultiMerger(const Compare& comp = Compare())
100             : IMultiMerger()
101             , m_data( MergeType(comp) )
102         { }
103         ~MultiMerger(void) { }
104
105     public:
106         void Add(MergeItem item);
107         void Clear(void);
108         const MergeItem& First(void) const;
109         bool IsEmpty(void) const;
110         void Remove(BamReader* reader);
111         int Size(void) const;
112         MergeItem TakeFirst(void);
113
114     private:
115         typedef MergeItem                              ValueType;
116         typedef std::multiset<ValueType, MergeType>    ContainerType;
117         typedef typename ContainerType::iterator       DataIterator;
118         typedef typename ContainerType::const_iterator DataConstIterator;
119         ContainerType m_data;
120 };
121
122 template <typename Compare>
123 inline void MultiMerger<Compare>::Add(MergeItem item) {
124     if ( CompareType::UsesCharData() )
125         item.Alignment->BuildCharData();
126     m_data.insert(item);
127 }
128
129 template <typename Compare>
130 inline void MultiMerger<Compare>::Clear(void) {
131     m_data.clear();
132 }
133
134 template <typename Compare>
135 inline const MergeItem& MultiMerger<Compare>::First(void) const {
136     const ValueType& entry = (*m_data.begin());
137     return entry;
138 }
139
140 template <typename Compare>
141 inline bool MultiMerger<Compare>::IsEmpty(void) const {
142     return m_data.empty();
143 }
144 template <typename Compare>
145 inline void MultiMerger<Compare>::Remove(BamReader* reader) {
146
147     if ( reader == 0 ) return;
148     const std::string& filenameToRemove = reader->GetFilename();
149
150     // iterate over readers in cache
151     DataIterator dataIter = m_data.begin();
152     DataIterator dataEnd  = m_data.end();
153     for ( ; dataIter != dataEnd; ++dataIter ) {
154         const MergeItem& item = (*dataIter);
155         const BamReader* itemReader = item.Reader;
156         if ( itemReader == 0 ) continue;
157
158         // remove iterator on match
159         if ( itemReader->GetFilename() == filenameToRemove ) {
160             m_data.erase(dataIter);
161             return;
162         }
163     }
164 }
165 template <typename Compare>
166 inline int MultiMerger<Compare>::Size(void) const {
167     return m_data.size();
168 }
169
170 template <typename Compare>
171 inline MergeItem MultiMerger<Compare>::TakeFirst(void) {
172     DataIterator firstIter = m_data.begin();
173     MergeItem    firstItem = (*firstIter);
174     m_data.erase(firstIter);
175     return firstItem;
176 }
177
178 // unsorted "merger"
179 template<>
180 class MultiMerger<Algorithms::Sort::Unsorted> : public IMultiMerger {
181
182     public:
183         explicit MultiMerger(const Algorithms::Sort::Unsorted& comp = Algorithms::Sort::Unsorted())
184             : IMultiMerger()
185         { }
186         ~MultiMerger(void) { }
187
188     public:
189         void Add(MergeItem item);
190         void Clear(void);
191         const MergeItem& First(void) const;
192         bool IsEmpty(void) const;
193         void Remove(BamReader* reader);
194         int Size(void) const;
195         MergeItem TakeFirst(void);
196
197     private:
198         typedef MergeItem                     ValueType;
199         typedef std::deque<ValueType>         ContainerType;
200         typedef ContainerType::iterator       DataIterator;
201         typedef ContainerType::const_iterator DataConstIterator;
202         ContainerType m_data;
203 };
204
205 inline
206 void MultiMerger<Algorithms::Sort::Unsorted>::Add(MergeItem item) {
207     m_data.push_back(item);
208 }
209
210 inline
211 void MultiMerger<Algorithms::Sort::Unsorted>::Clear(void) {
212     m_data.clear();
213 }
214
215 inline
216 const MergeItem& MultiMerger<Algorithms::Sort::Unsorted>::First(void) const {
217     return m_data.front();
218 }
219
220 inline
221 bool MultiMerger<Algorithms::Sort::Unsorted>::IsEmpty(void) const {
222     return m_data.empty();
223 }
224
225 inline
226 void MultiMerger<Algorithms::Sort::Unsorted>::Remove(BamReader* reader) {
227
228     if ( reader == 0 ) return;
229     const std::string filenameToRemove = reader->GetFilename();
230
231     // iterate over readers in cache
232     DataIterator dataIter = m_data.begin();
233     DataIterator dataEnd  = m_data.end();
234     for ( ; dataIter != dataEnd; ++dataIter ) {
235         const MergeItem& item = (*dataIter);
236         const BamReader* itemReader = item.Reader;
237         if ( itemReader == 0 ) continue;
238
239         // remove iterator on match
240         if ( itemReader->GetFilename() == filenameToRemove ) {
241             m_data.erase(dataIter);
242             return;
243         }
244     }
245 }
246
247 inline
248 int MultiMerger<Algorithms::Sort::Unsorted>::Size(void) const {
249     return m_data.size();
250 }
251
252 inline
253 MergeItem MultiMerger<Algorithms::Sort::Unsorted>::TakeFirst(void) {
254     MergeItem firstItem = m_data.front();
255     m_data.pop_front();
256     return firstItem;
257 }
258
259 } // namespace Internal
260 } // namespace BamTools
261
262 #endif // BAMMULTIMERGER_P_H