<commit_before>/** @file
    @brief Header defining buffer types, with optional alignment dependent on
   Boost version.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

#ifndef INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D
#define INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D

// Internal Includes
// - none

// Library/third-party includes
#include <boost/version.hpp>

#if BOOST_VERSION >= 105600
#include <boost/align/aligned_allocator.hpp>
#endif

// Standard includes
#include <vector>
#include <stdexcept>
#include <algorithm>

namespace osvr {
namespace common {
    /// @brief The single-byte element in a buffer.
    typedef char BufferElement;

    /// @brief Traits class specifying the (potentially platform-specific!)
    /// preferred alignment for Buffer.
    struct DesiredBufferAlignment {
        /// @brief Alignment in bytes
        static const size_t value = 16;
    };
#if BOOST_VERSION >= 105600
    // New Boost has code to handle aligned allocation. Alignment is hard to do
    // portably so we are happy to delegate.

    /// @brief Traits class describing actual alignment of Buffer.
    struct ActualBufferAlignment : DesiredBufferAlignment {};

    /// @brief Allocator type for Buffer - might be usefully aligned.
    typedef boost::alignment::aligned_allocator<
        BufferElement, ::osvr::common::DesiredBufferAlignment::value>
        BufferAllocator;

#else
    // Fallback for older boost: unaligned buffer. Want to rely on aligned
    // buffers? Upgrade Boost and rebuild.

    /// @brief Traits class describing actual alignment of Buffer.
    struct ActualBufferAlignment {
        static const size_t value = 1;
    };

    /// @brief Allocator type for Buffer - might be usefully aligned.
    typedef std::allocator<BufferElement> BufferAllocator;
#endif

    /// @brief A typedef for a buffer (a vector of bytes), that might be
    /// "over-aligned" in some desirable way.
    ///
    /// Check ActualBufferAlignment::value to see if it is actually aligned.
    typedef std::vector<BufferElement, BufferAllocator> Buffer;

    /// @brief Given an alignment in bytes, and a current size of a buffer,
    /// return the number of bytes of padding required to align the next field
    /// to be added to the buffer at the desired alignment.
    ///
    /// That is, return some padding such that (currentSize + padding) %
    /// alignment == 0 for alignment > 1.
    ///
    /// @param alignment Alignment in bytes: both 0 and 1 are accepted to mean
    /// "no alignment"
    /// @param currentSize Current number of bytes in a buffer
    inline size_t computeAlignmentPadding(size_t alignment,
                                          size_t currentSize) {

        size_t ret = 0;
        if (2 > alignment) {
            return ret;
        }
        auto leftover = currentSize % alignment;
        if (leftover == 0) {
            return ret;
        }
        ret = alignment - leftover;
        return ret;
    }

    template <typename BufferType = Buffer> class BufferWrapper {
      public:
        class Reader {
          public:
            size_t bytesRead() const { return m_readIter - m_begin; }
            size_t remaining() const { return m_end - m_readIter; }
            /// @brief Get the binary representation of a type from a buffer
            template <typename T> void read(T &v) {
                if (remaining() < sizeof(T)) {
                    throw std::runtime_error(
                        "Not enough data in the buffer to read this type!");
                }
                ElementType const *dest =
                    reinterpret_cast<ElementType const *>(&v);

                auto readEnd = m_readIter + sizeof(T);
                std::copy(m_readIter, readEnd, dest);
                m_readIter = readEnd;
            }

            /// @brief Skip reading the given number of bytes, assumed to be
            /// padding.
            void skipPadding(size_t const bytes) {
                if (bytes == 0) {
                    return;
                }
                if (remaining() < bytes) {
                    throw std::runtime_error("Can't skip that many padding "
                                             "bytes, not that many bytes "
                                             "left!");
                }
                m_readIter += bytes;
            }

          private:
            typedef typename BufferType::const_iterator const_iterator;
            Reader(BufferType const &buf)
                : m_buf(&buf), m_begin(m_buf->begin()),
                  m_readIter(m_buf->begin()), m_end(m_buf->end()) {}
            BufferType const *m_buf;
            const_iterator m_begin;
            const_iterator m_readIter;
            const_iterator m_end;
            typedef typename BufferType::value_type ElementType;
            friend class BufferWrapper;
        };

        typedef typename BufferType::value_type ElementType;

        /// @brief Constructs an empty buffer
        BufferWrapper(){};

        /// @brief Constructs a buffer wrapper by copy-constructing the
        /// contained buffer type.
        explicit BufferWrapper(BufferType const &buf) : m_buf(buf) {}

        /// @brief Append the binary representation of a value
        template <typename T> void append(T const v) {
            ElementType const *src = reinterpret_cast<ElementType const *>(&v);
            m_buf.insert(m_buf.end(), src, src + sizeof(T));
        }

        /// @brief Append a byte-array's contents
        void append(ElementType const *v, size_t n) {
            m_buf.insert(m_buf.end(), v, v + n);
        }
<commit_msg>Annotate bits that look like violating strict aliasing but aren't.<commit_after>/** @file
    @brief Header defining buffer types, with optional alignment dependent on
   Boost version.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

#ifndef INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D
#define INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D

// Internal Includes
// - none

// Library/third-party includes
#include <boost/version.hpp>

#if BOOST_VERSION >= 105600
#include <boost/align/aligned_allocator.hpp>
#endif

// Standard includes
#include <vector>
#include <stdexcept>
#include <algorithm>

namespace osvr {
namespace common {
    /// @brief The single-byte element in a buffer.
    typedef char BufferElement;

    /// @brief Traits class specifying the (potentially platform-specific!)
    /// preferred alignment for Buffer.
    struct DesiredBufferAlignment {
        /// @brief Alignment in bytes
        static const size_t value = 16;
    };
#if BOOST_VERSION >= 105600
    // New Boost has code to handle aligned allocation. Alignment is hard to do
    // portably so we are happy to delegate.

    /// @brief Traits class describing actual alignment of Buffer.
    struct ActualBufferAlignment : DesiredBufferAlignment {};

    /// @brief Allocator type for Buffer - might be usefully aligned.
    typedef boost::alignment::aligned_allocator<
        BufferElement, ::osvr::common::DesiredBufferAlignment::value>
        BufferAllocator;

#else
    // Fallback for older boost: unaligned buffer. Want to rely on aligned
    // buffers? Upgrade Boost and rebuild.

    /// @brief Traits class describing actual alignment of Buffer.
    struct ActualBufferAlignment {
        static const size_t value = 1;
    };

    /// @brief Allocator type for Buffer - might be usefully aligned.
    typedef std::allocator<BufferElement> BufferAllocator;
#endif

    /// @brief A typedef for a buffer (a vector of bytes), that might be
    /// "over-aligned" in some desirable way.
    ///
    /// Check ActualBufferAlignment::value to see if it is actually aligned.
    typedef std::vector<BufferElement, BufferAllocator> Buffer;

    /// @brief Given an alignment in bytes, and a current size of a buffer,
    /// return the number of bytes of padding required to align the next field
    /// to be added to the buffer at the desired alignment.
    ///
    /// That is, return some padding such that (currentSize + padding) %
    /// alignment == 0 for alignment > 1.
    ///
    /// @param alignment Alignment in bytes: both 0 and 1 are accepted to mean
    /// "no alignment"
    /// @param currentSize Current number of bytes in a buffer
    inline size_t computeAlignmentPadding(size_t alignment,
                                          size_t currentSize) {

        size_t ret = 0;
        if (2 > alignment) {
            return ret;
        }
        auto leftover = currentSize % alignment;
        if (leftover == 0) {
            return ret;
        }
        ret = alignment - leftover;
        return ret;
    }

    template <typename BufferType = Buffer> class BufferWrapper {
      public:
        class Reader {
          public:
            size_t bytesRead() const { return m_readIter - m_begin; }
            size_t remaining() const { return m_end - m_readIter; }
            /// @brief Get the binary representation of a type from a buffer
            template <typename T> void read(T &v) {
                if (remaining() < sizeof(T)) {
                    throw std::runtime_error(
                        "Not enough data in the buffer to read this type!");
                }
                /// Safe to do without violating strict aliasing because
                /// ElementType is a character type.
                ElementType const *dest =
                    reinterpret_cast<ElementType const *>(&v);

                auto readEnd = m_readIter + sizeof(T);
                std::copy(m_readIter, readEnd, dest);
                m_readIter = readEnd;
            }

            /// @brief Skip reading the given number of bytes, assumed to be
            /// padding.
            void skipPadding(size_t const bytes) {
                if (bytes == 0) {
                    return;
                }
                if (remaining() < bytes) {
                    throw std::runtime_error("Can't skip that many padding "
                                             "bytes, not that many bytes "
                                             "left!");
                }
                m_readIter += bytes;
            }

          private:
            typedef typename BufferType::const_iterator const_iterator;
            Reader(BufferType const &buf)
                : m_buf(&buf), m_begin(m_buf->begin()),
                  m_readIter(m_buf->begin()), m_end(m_buf->end()) {}
            BufferType const *m_buf;
            const_iterator m_begin;
            const_iterator m_readIter;
            const_iterator m_end;
            typedef typename BufferType::value_type ElementType;
            friend class BufferWrapper;
        };

        typedef typename BufferType::value_type ElementType;

        /// @brief Constructs an empty buffer
        BufferWrapper(){};

        /// @brief Constructs a buffer wrapper by copy-constructing the
        /// contained buffer type.
        explicit BufferWrapper(BufferType const &buf) : m_buf(buf) {}

        /// @brief Append the binary representation of a value
        template <typename T> void append(T const v) {
            /// Safe to do without violating strict aliasing because ElementType
            /// is a character type.
            ElementType const *src = reinterpret_cast<ElementType const *>(&v);
            m_buf.insert(m_buf.end(), src, src + sizeof(T));
        }

        /// @brief Append a byte-array's contents
        void append(ElementType const *v, size_t n) {
            m_buf.insert(m_buf.end(), v, v + n);
        }

{'fraction_non_alphanumeric': 0.08878154409927543, 'fraction_numerical': 0.01249271258432581, 'mean_word_length': 1.9730131220599159, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2231934', 'n_tokens_mistral': 3282, 'n_tokens_neox': 3077, 'n_words': 1087}