]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamMultiMerger_p.h
2b7b110ad1ae4967ef086273f32650ea4fc6d848
[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
125     // N.B. - any future custom Compare types must define this method
126     //        see algorithms/Sort.h
127
128     if ( CompareType::UsesCharData() )
129         item.Alignment->BuildCharData();
130     m_data.insert(item);
131 }
132
133 template <typename Compare>
134 inline void MultiMerger<Compare>::Clear(void) {
135     m_data.clear();
136 }
137
138 template <typename Compare>
139 inline const MergeItem& MultiMerger<Compare>::First(void) const {
140     const ValueType& entry = (*m_data.begin());
141     return entry;
142 }
143
144 template <typename Compare>
145 inline bool MultiMerger<Compare>::IsEmpty(void) const {
146     return m_data.empty();
147 }
148 template <typename Compare>
149 inline void MultiMerger<Compare>::Remove(BamReader* reader) {
150
151     if ( reader == 0 ) return;
152     const std::string& filenameToRemove = reader->GetFilename();
153
154     // iterate over readers in cache
155     DataIterator dataIter = m_data.begin();
156     DataIterator dataEnd  = m_data.end();
157     for ( ; dataIter != dataEnd; ++dataIter ) {
158         const MergeItem& item = (*dataIter);
159         const BamReader* itemReader = item.Reader;
160         if ( itemReader == 0 ) continue;
161
162         // remove iterator on match
163         if ( itemReader->GetFilename() == filenameToRemove ) {
164             m_data.erase(dataIter);
165             return;
166         }
167     }
168 }
169 template <typename Compare>
170 inline int MultiMerger<Compare>::Size(void) const {
171     return m_data.size();
172 }
173
174 template <typename Compare>
175 inline MergeItem MultiMerger<Compare>::TakeFirst(void) {
176     DataIterator firstIter = m_data.begin();
177     MergeItem    firstItem = (*firstIter);
178     m_data.erase(firstIter);
179     return firstItem;
180 }
181
182 // unsorted "merger"
183 template<>
184 class MultiMerger<Algorithms::Sort::Unsorted> : public IMultiMerger {
185
186     public:
187         explicit MultiMerger(const Algorithms::Sort::Unsorted& comp = Algorithms::Sort::Unsorted())
188             : IMultiMerger()
189         { }
190         ~MultiMerger(void) { }
191
192     public:
193         void Add(MergeItem item);
194         void Clear(void);
195         const MergeItem& First(void) const;
196         bool IsEmpty(void) const;
197         void Remove(BamReader* reader);
198         int Size(void) const;
199         MergeItem TakeFirst(void);
200
201     private:
202         typedef MergeItem                     ValueType;
203         typedef std::deque<ValueType>         ContainerType;
204         typedef ContainerType::iterator       DataIterator;
205         typedef ContainerType::const_iterator DataConstIterator;
206         ContainerType m_data;
207 };
208
209 inline
210 void MultiMerger<Algorithms::Sort::Unsorted>::Add(MergeItem item) {
211     m_data.push_back(item);
212 }
213
214 inline
215 void MultiMerger<Algorithms::Sort::Unsorted>::Clear(void) {
216     m_data.clear();
217 }
218
219 inline
220 const MergeItem& MultiMerger<Algorithms::Sort::Unsorted>::First(void) const {
221     return m_data.front();
222 }
223
224 inline
225 bool MultiMerger<Algorithms::Sort::Unsorted>::IsEmpty(void) const {
226     return m_data.empty();
227 }
228
229 inline
230 void MultiMerger<Algorithms::Sort::Unsorted>::Remove(BamReader* reader) {
231
232     if ( reader == 0 ) return;
233     const std::string filenameToRemove = reader->GetFilename();
234
235     // iterate over readers in cache
236     DataIterator dataIter = m_data.begin();
237     DataIterator dataEnd  = m_data.end();
238     for ( ; dataIter != dataEnd; ++dataIter ) {
239         const MergeItem& item = (*dataIter);
240         const BamReader* itemReader = item.Reader;
241         if ( itemReader == 0 ) continue;
242
243         // remove iterator on match
244         if ( itemReader->GetFilename() == filenameToRemove ) {
245             m_data.erase(dataIter);
246             return;
247         }
248     }
249 }
250
251 inline
252 int MultiMerger<Algorithms::Sort::Unsorted>::Size(void) const {
253     return m_data.size();
254 }
255
256 inline
257 MergeItem MultiMerger<Algorithms::Sort::Unsorted>::TakeFirst(void) {
258     MergeItem firstItem = m_data.front();
259     m_data.pop_front();
260     return firstItem;
261 }
262
263 } // namespace Internal
264 } // namespace BamTools
265
266 #endif // BAMMULTIMERGER_P_H