10 #ifndef BAMALIGNMENT_H
11 #define BAMALIGNMENT_H
27 class BamReaderPrivate;
28 class BamWriterPrivate;
42 bool IsDuplicate()
const;
43 bool IsFailedQC()
const;
44 bool IsFirstMate()
const;
45 bool IsMapped()
const;
46 bool IsMateMapped()
const;
47 bool IsMateReverseStrand()
const;
48 bool IsPaired()
const;
49 bool IsSupplementary()
const;
50 bool IsPrimaryAlignment()
const;
53 bool IsReverseStrand()
const;
54 bool IsSecondMate()
const;
58 void SetIsDuplicate(
bool ok);
59 void SetIsFailedQC(
bool ok);
60 void SetIsFirstMate(
bool ok);
61 void SetIsMapped(
bool ok);
62 void SetIsMateMapped(
bool ok);
63 void SetIsMateReverseStrand(
65 void SetIsPaired(
bool ok);
66 void SetIsPrimaryAlignment(
bool ok);
70 void SetIsReverseStrand(
bool ok);
71 void SetIsSecondMate(
bool ok);
77 bool AddTag(
const std::string& tag,
const std::string& type,
const T& value);
79 bool AddTag(
const std::string& tag,
const std::vector<T>& values);
83 bool EditTag(
const std::string& tag,
const std::string& type,
const T& value);
85 bool EditTag(
const std::string& tag,
const std::vector<T>& values);
89 bool GetTag(
const std::string& tag, T& destination)
const;
91 bool GetTag(
const std::string& tag, std::vector<T>& destination)
const;
94 std::vector<std::string> GetTagNames()
const;
97 bool GetTagType(
const std::string& tag,
char& type)
const;
100 bool GetArrayTagType(
const std::string& tag,
char& type)
const;
103 bool HasTag(
const std::string& tag)
const;
106 void RemoveTag(
const std::string& tag);
111 bool BuildCharData();
114 int GetEndPosition(
bool usePadded =
false,
bool closedInterval =
false)
const;
117 std::string GetErrorString()
const;
120 bool GetSoftClips(std::vector<int>& clipSizes, std::vector<int>& readPositions,
121 std::vector<int>& genomePositions,
bool usePadded =
false)
const;
146 bool FindTag(
const std::string& tag,
char*& pTagData,
const unsigned int& tagDataLength,
147 unsigned int& numBytesParsed)
const;
148 bool IsValidSize(
const std::string& tag,
const std::string& type)
const;
149 void SetErrorString(
const std::string& where,
const std::string& what)
const;
150 bool SkipToNextTag(
const char storageType,
char*& pTagData,
unsigned int& numBytesParsed)
const;
155 struct BamAlignmentSupportData
160 std::string AllCharData;
161 uint32_t BlockLength;
162 uint32_t NumCigarOperations;
163 uint32_t QueryNameLength;
164 uint32_t QuerySequenceLength;
169 BamAlignmentSupportData()
171 , NumCigarOperations(0)
173 , QuerySequenceLength(0)
177 BamAlignmentSupportData SupportData;
178 friend class Internal::BamReaderPrivate;
179 friend class Internal::BamWriterPrivate;
181 mutable std::string ErrorString;
198 template <
typename T>
203 if (SupportData.HasCoreOnly) {
208 if (!IsValidSize(tag, type)) {
214 if (!TagTypeHelper<T>::CanConvertTo(type.at(0))) {
220 char* pTagData = (
char*)
TagData.data();
221 const unsigned int tagDataLength =
TagData.size();
222 unsigned int numBytesParsed = 0;
226 if (FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
235 char valueBuffer[
sizeof(T)];
240 const std::string newTag = tag + type;
241 const std::size_t newTagDataLength =
242 tagDataLength + newTag.size() +
sizeof(T);
243 RaiiBuffer originalTagData(newTagDataLength);
244 std::memcpy(originalTagData.Buffer,
TagData.c_str(),
248 std::strcat(originalTagData.Buffer + tagDataLength, newTag.data());
249 std::memcpy(originalTagData.Buffer + tagDataLength + newTag.size(), un.valueBuffer,
sizeof(T));
252 const char* newTagData = (
const char*)originalTagData.Buffer;
253 TagData.assign(newTagData, newTagDataLength);
258 inline bool BamAlignment::AddTag<std::string>(
const std::string& tag,
const std::string& type,
259 const std::string& value)
262 if (SupportData.HasCoreOnly) {
267 if (!IsValidSize(tag, type)) {
273 if (!TagTypeHelper<std::string>::CanConvertTo(type.at(0))) {
279 char* pTagData = (
char*)TagData.data();
280 const unsigned int tagDataLength = TagData.size();
281 unsigned int numBytesParsed = 0;
285 if (FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
291 const std::string newTag = tag + type + value;
292 const std::size_t newTagDataLength =
293 tagDataLength + newTag.size() + 1;
294 RaiiBuffer originalTagData(newTagDataLength);
295 std::memcpy(originalTagData.Buffer, TagData.c_str(),
299 std::strcat(originalTagData.Buffer + tagDataLength, newTag.data());
302 const char* newTagData = (
const char*)originalTagData.Buffer;
303 TagData.assign(newTagData, newTagDataLength);
317 template <
typename T>
322 if (SupportData.HasCoreOnly) {
332 char* pTagData = (
char*)
TagData.data();
333 const unsigned int tagDataLength =
TagData.size();
334 unsigned int numBytesParsed = 0;
338 if (FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
347 newTagBase[3] = TagTypeHelper<T>::TypeCode();
350 const int32_t numElements = values.size();
351 std::memcpy(newTagBase + 4, &numElements,
sizeof(int32_t));
354 const std::size_t newTagDataLength =
356 RaiiBuffer originalTagData(newTagDataLength);
357 std::memcpy(originalTagData.Buffer,
TagData.c_str(),
361 std::strcat(originalTagData.Buffer + tagDataLength, (
const char*)newTagBase);
365 for (
int i = 0; i < numElements; ++i) {
366 const T& value = values.at(i);
367 std::memcpy(originalTagData.Buffer + elementsBeginOffset + i *
sizeof(T), &value,
372 const char* newTagData = (
const char*)originalTagData.Buffer;
373 TagData.assign(newTagData, newTagDataLength);
391 template <
typename T>
396 if (SupportData.HasCoreOnly) {
404 return AddTag(tag, type, value);
418 template <
typename T>
423 if (SupportData.HasCoreOnly) {
431 return AddTag(tag, values);
441 template <
typename T>
446 if (SupportData.HasCoreOnly) {
458 char* pTagData = (
char*)
TagData.data();
459 const unsigned int tagDataLength =
TagData.size();
460 unsigned int numBytesParsed = 0;
463 if (!FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
469 const char type = *(pTagData - 1);
470 if (!TagTypeHelper<T>::CanConvertFrom(type)) {
476 int destinationLength = 0;
483 destinationLength = 1;
489 destinationLength = 2;
496 destinationLength = 4;
503 SetErrorString(
"BamAlignment::GetTag",
504 "cannot store variable length tag data into a numeric destination");
509 const std::string message = std::string(
"invalid tag type: ") + type;
510 SetErrorString(
"BamAlignment::GetTag", message);
516 std::memcpy(&destination, pTagData, destinationLength);
523 inline bool BamAlignment::GetTag<std::string>(
const std::string& tag,
524 std::string& destination)
const
527 if (SupportData.HasCoreOnly) {
533 if (TagData.empty()) {
539 char* pTagData = (
char*)TagData.data();
540 const unsigned int tagDataLength = TagData.size();
541 unsigned int numBytesParsed = 0;
544 if (!FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
550 const unsigned int dataLength = std::strlen(pTagData);
552 destination.resize(dataLength);
553 std::memcpy((
char*)destination.data(), pTagData, dataLength);
566 template <
typename T>
571 if (SupportData.HasCoreOnly) {
583 char* pTagData = (
char*)
TagData.data();
584 const unsigned int tagDataLength =
TagData.size();
585 unsigned int numBytesParsed = 0;
588 if (!FindTag(tag, pTagData, tagDataLength, numBytesParsed)) {
594 const char tagType = *(pTagData - 1);
596 SetErrorString(
"BamAlignment::GetTag",
"cannot store a non-array tag in array destination");
601 const char elementType = *pTagData;
602 if (!TagTypeHelper<T>::CanConvertFrom(elementType)) {
609 switch (elementType) {
628 SetErrorString(
"BamAlignment::GetTag",
629 "invalid array data, variable-length elements are not allowed");
634 const std::string message = std::string(
"invalid array element type: ") + elementType;
635 SetErrorString(
"BamAlignment::GetTag", message);
641 std::memcpy(&numElements, pTagData,
sizeof(int32_t));
644 destination.reserve(numElements);
648 for (
int i = 0; i < numElements; ++i) {
649 std::memcpy(&value, pTagData,
sizeof(T));
650 pTagData +=
sizeof(T);
651 destination.push_back(value);