/*!
* @class BamTagsDict
*
* @headerfile <seqan/bam_io.h>
*
* @brief Indexes start positions of BAM tags in a @link CharString @endlink and
* provides a dict-like API.
*
* @signature class BamTagsDict;
*
* @section Example
*
* @include demos/dox/bam_io/bam_tags_dict.cpp
*
* Output is:
*
* @include demos/dox/bam_io/bam_tags_dict.cpp.stdout
*
* @see getBamTypeSize
* @see getBamTypeChar
*
* @fn BamTagsDict::BamTagsDict
*
* @brief Constructor
*
* @signature BamTagsDict::BamTagsDict();
* @signature BamTagsDict::BamTagsDict(tags);
*
* @param[in,out] tags The tags string of a @link BamAlignmentRecord @endlink to
* be indexed and or modified.
*
* Note, the second constructor stores a reference to <tt>tags</tt> using a
* @link Holder @endlink. In case of modifying the BamTagsDict by adding or
* removing tags those changes will be transparently transferred to the origin
* of <tt>tags</tt>.
*
* @fn BamTagsDict#hasIndex
*
* @brief Returns whether the BamTagsDict has an index.
*
* @signature bool hasIndex(tagsDict);
*
* @param[in] tagsDict The @link BamTagsDict @endlink to query.
*
* @return bool <tt>true</tt> if <tt>dict</tt> has an index and <tt>false</tt>
* otherwise.
*
* @fn BamTagsDict#buildIndex
*
* @brief Build index for a BamTagsDict object.
*
* @signature void buildIndex(tagsDict);
*
* @param[in,out] tagsDict The BamTagsDict object to build the index for.
*
* @fn BamTagsDict#length
*
* @brief Returns the number of entries in a BamTagsDict.
*
* @signature unsigned length(tagsDict);
*
* @param[in] tagsDict The BamTagsDict object to query for its length.
*
* @return TSize The number of entries in the BamTagsDict. <tt>TSize</tt> is the
* result of <tt>Size<BamTagsDict>::Type</tt>.
*
* @fn BamTagsDict#getTagType
*
* @brief Returns the tag type char for an entry of a BamTagsDict.
*
* @signature char getTagType(tagsDict, id);
*
* @param[in] tagsDict The BamTagsDict to query.
* @param[in] id The id of the tag for which to determine the type. See @link
* BamTagsDict#findTagKey @endlink.
*
* @return char A <tt>char</tt> that identifies the tag type.
*
* @fn BamTagsDict#getTagKey
*
* @brief Return key of a tag by index.
*
* @signature TKey getTagKey(tagsDict, id);
*
* @param[in] tagsDict The BamTagsDict to query.
* @param[in] id The index of the dict entry.
*
* @return TKey An infix of a @link CharString @endlink. Will be a two-character
* char sequence.
*
* @fn BamTagsDict#findTagKey
*
* @brief Find a tag by its key for a @link BamTagsDict @endlink object.
*
* @signature bool findTagKey(id, tagsDict, key);
*
* @param[out] id The id of the found tag.
* @param[in] tagsDict The BamTagsDict to query.
* @param[in] key The key to query for: @link CharString @endlink.
*
* @return bool <tt>true</tt> if the key could be found and <tt>false</tt>
* otherwise.
*
* @fn BamTagsDict#extractTagValue
*
* @brief Extract and cast "atomic" value from tags string with index
* <tt>id</tt>.
*
* @signature bool extractTagValue(dest, tagsDict, id)
*
* @param[out] dest The variable to write the value to.The value is first copied
* in a variable of the type indicated in the BAM file. Then it
* is cast into the type of <tt>dest</tt>.
* @param[in] tagsDict The BamTagsDict object to query.
* @param[in] id The id of the tag to extract the value from. See @link
* BamTagsDict#findTagKey @endlink.
*
* @return bool <tt>true</tt> if the value could be extracted.
*
* @section Remarks
*
* The function only works for atomic types such as <tt>int</tt>, not for
* <tt>char*</tt> or arrays.
*
* See @link BamTagsDict @endlink for an example.
*
* @fn BamTagsDict#setTagValue
*
* @headerfile <seqan/bam_io.h>
*
* @brief Set the value of a tag through a @link BamTagsDict @endlink.
*
* @signature bool setTagValue(tagsDict, key, val[, typeC]);
*
* @param[in,out] tagsDict The BamTagsDict to modify.
* @param[in] key The key of the tag. Must be a sequence of length 2.
* @param[in] val The value to set the tag to.
* @param[in] typeC BAM type char to use. For portability (so the generated
* files are the same on all platforms), use a signed/unsigned
* qualified type for <tt>val</tt> or give <tt>typeC</tt>. Also
* see the remarks for @link getBamTypeChar @endlink. Types:
* getBamTypeChar@.
*
* @return bool <tt>true</tt> on success, <tt>false</tt> on failure. This
* function can fail if the key is not a valid tag id (e.g. does
* not have length 2) or if the type of <tt>val</tt> is not an
* atomic value or a string (anything but <tt>char *</tt>, <tt>char
* const *</tt>, a character, integer or float type is invalid).
*
* @section Remarks
*
* Note that <tt>setTagValue</tt> does not cast the type, so <tt>typeC</tt> only
* influences the type character written out but <tt>val</tt> is written out in
* binary without modification.
*
* @section Examples
*
* An example setting some atomic tag values.
*
* @code{.cpp}
* CharString rawTagsText;
* BamTagsDict tags(rawTagsText);
* setTagValue(tags, "XA", 9); // int
* setTagValue(tags, "XB", 9u); // unsigned int
* setTagValue(tags, "XC", 'X'); // char
* @endcode
*
*
* If <tt>char</tt> is equal to <tt>int8_t</tt> or <tt>uint8_t</tt> then the
* last line produces an entry with type 'c' or 'C'. To make sure that the type
* char 'A' (for "printable character") is written to the file, give it
* explicitely:
*
* @code{.cpp}
* setTagValue(tags, "XC", 'X', 'A'); // Overrwrite XC, enforce type 'printable character'.
* @endcode
*
*
* Note that on most systems <tt>int</tt>s have a width of 32 bytes, but the C++
* standard leaves this open. For all types but characters, you should not give
* an explicit type char but use one of the types with explicit width and
* signed/unsigned qualifier such as <tt>int32_t</tt>, <tt>uint32_t</tt> etc.
*
* @code{.cpp}
* // The following is not recommended since the type of <tt>x</tt> is not "unsigned 32 bit int."
* int32_t x = -1;
* setTagValue(tags, "XB", x, 'I');
* // Instead, explicitely use an unsigned type if you need one. Note that your compiler
* // might warn you about assigning -1 to an unsigned variable so you know that you are
* // probably doing something unintended.
* uint32_t y = -1;
* setTagValue(tags, "XB", y);
*
* // Do not do this!
* setTagValue(tags, "XA", 9, 'f'); // BOGUS since 9 is not a floating point number.
* @endcode
*
*
* @see getBamTypeChar
*
* @fn BamTagsDict#appendTagValue
*
* @headerfile <seqan/bam_io.h>
*
* @brief Append a tag/value pair to a @link BamTagsDict @endlink.
*
* @signature bool appendTagValue(tagsDict, key, val[, typeC]);
*
* @param[in,out] tagsDict The BamTagsDict to modify.
* @param[in] key The key of the tag. Must be a sequence of length 2.
* @param[in] val The value to set the tag to.
* @param[in] typeC BAM type char to use. For portability (so the generated
* files are the same on all platforms), use a signed/unsigned
* qualified type for <tt>val</tt> or give <tt>typeC</tt>. Also
* see the remarks for @link getBamTypeChar @endlink. Types:
* getBamTypeChar@.
*
* @return bool <tt>true</tt> on success, <tt>false</tt> on failure. This
* function can fail if the key is not a valid tag id (e.g. does
* not have length 2) or if the type of <tt>val</tt> is not an
* atomic value or a string (anything but <tt>char *</tt>, <tt>char
* const *</tt>, a character, integer or float type is invalid).
*
* @section Remarks
*
* @link BamTagsDict#setTagValue @endlink behaves like <tt>appendTagValue</tt>
* if <tt>key</tt> was not part of <tt>tags</tt> before. However, in this case
* <tt>appendTagValue</tt> is faster.
*
* @fn BamTagsDict#eraseTag
*
* @brief Erase a tag from BamTagsDict.
*
* @signature bool eraseTag(tagsDict, key);
*
* @param[in,out] tagsDict The BamTagsDict to erase the tag from.
* @param[in] key The key of the tag to erase.
*
* @return bool <tt>true</tt> if the tag could be erased, <tt>false</tt> if the
* key wasn't present.
*
* @fn BamTagsDict#tagsToBamRecord
*
* @brief Writes bam tags to the <tt>tags</tt> field of the given @link
* BamAlignmentRecord @endlink.
*
* @signature void tagsToBamRecord(record, tagsDict)
*
* @param[out] record The @link BamAlignmentRecord @endlink whose tags field is
* overwritten.
* @param[in] tagsDict The @link BamTagsDict @endlink to get the tags from.
*
* This is semantically the same as:
*
* @code{.cpp}
* record.tags = host(tagsDict);
* @endcode
*
*
* See @link BamTagsDict @endlink for an example.
*/