Skip to content

Prototypes:dna.hpp

Hannes Hauswedell edited this page Feb 1, 2017 · 4 revisions

dna.hpp

#pragma once

#include "alphabet.hpp"

namespace seqan3
{

struct dna
{
    using inner_type = uint8_t;

    enum val : inner_type
    {
        A,
        C,
        G,
        T,
        UNKNOWN = A
    };

    inner_type value;

    // Rule-of-five
    dna() = default;
    constexpr dna(dna const &) = default;
    constexpr dna(dna &&) = default;
    constexpr dna & operator=(dna const &) = default;
    constexpr dna & operator=(dna &&) = default;

    // compatibility to char TODO explicit or implicit?
    constexpr dna(char const c) :
        value{char_to_value[static_cast<inner_type>(c)]}
    {}

    constexpr dna & operator=(char const c)
    {
        value = char_to_value[static_cast<inner_type>(c)];
    }

    explicit constexpr operator char() const
    {
        return value_to_char[value];
    }

    // conversion tables
    static constexpr uint8_t value_size{4};

    static constexpr char value_to_char[value_size]
    {
        'A',
        'C',
        'G',
        'T'
    };

    static constexpr val char_to_value[256]
    {
         // similar to https://github.com/seqan/seqan/blob/master/include/seqan/basic/alphabet_residue_tabs.h#L76
         // possibly with enum values instead
    };

    /* comparison operators */
    constexpr bool operator ==(dna const & rhs) const noexcept
    {
        return value == rhs.value;
    }

    constexpr bool operator !=(dna const & rhs) const noexcept
    {
        return value != rhs.value;
    }

    constexpr bool operator <(dna const & rhs) const noexcept
    {
        return value < rhs.value;
    }

    constexpr bool operator >(dna const & rhs) const noexcept
    {
        return value > rhs.value;
    }

    constexpr bool operator <=(dna const & rhs) const noexcept
    {
        return value <= rhs.value;
    }

    constexpr bool operator >=(dna const & rhs) const noexcept
    {
        return value >= rhs.value;
    }
};

// shall fulfill Alphabet concept
static_assert(Alphabet<dna>);
static_assert(dna{'A'} == dna{});
static_assert(static_cast<char>(dna{'A'}) == 'A');
static_assert(dna{'A'} == 'A');
static_assert(dna{'A'} < dna{'C'});

}

Open questions

  • should we have the enum at all?
  • if yes, should the base type be the enum?
  • or do we want to use a strongly typed enum instead of the char constructor?
  • if yes, we need to keep in mind that this always implies another scope, makes it harder to read

dna4_container.hpp

#pragma once

#include <iostream>
#include <string>
#include <vector>

#include "alphabet.hpp"
#include "alphabet_container.hpp"
#include "dna.hpp"

// ------------------------------------------------------------------
// traits
// ------------------------------------------------------------------

namespace std
{

template<>
struct char_traits<seqan3::dna> : public seqan3::alphabet_traits<seqan3::dna>
{
};

} // namespace std

// ------------------------------------------------------------------
// containers
// -----------------------------------------------------------------

namespace seqan3
{

using dna_string = std::basic_string<dna, alphabet_traits<dna>>;

using dna_vector = std::vector<dna>;

} // namespace seqan3

// ------------------------------------------------------------------
// literals
// -----------------------------------------------------------------

namespace seqan3::literal
{

inline dna_string operator "" _dna(const char * s, std::size_t n)
{
    dna_string r;
    r.resize(n);

    std::transform(s, s + n, r.begin(), [] (const char & c)
    {
        return dna{c};
    });

    return r;
}

} // namespace seqan3::literal
Clone this wiki locally