Cleaned up and updated the test; the code was written with a pre-C99 standard in mind. Added a get() method into mxs::Buffer to make it easier to use with non-C++ functions.
		
			
				
	
	
		
			712 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			712 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
/*
 | 
						|
 * Copyright (c) 2016 MariaDB Corporation Ab
 | 
						|
 *
 | 
						|
 * Use of this software is governed by the Business Source License included
 | 
						|
 * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | 
						|
 *
 | 
						|
 * Change Date: 2020-01-01
 | 
						|
 *
 | 
						|
 * On the date above, in accordance with the Business Source License, use
 | 
						|
 * of this software will be governed by version 2 or later of the General
 | 
						|
 * Public License.
 | 
						|
 */
 | 
						|
 | 
						|
#include <maxscale/cppdefs.hh>
 | 
						|
#include <algorithm>
 | 
						|
#include <iterator>
 | 
						|
#include <new>
 | 
						|
#include <vector>
 | 
						|
#include <maxscale/buffer.h>
 | 
						|
 | 
						|
namespace maxscale
 | 
						|
{
 | 
						|
 | 
						|
/**
 | 
						|
 * @class Buffer
 | 
						|
 *
 | 
						|
 * @c Buffer is a simple wrapper around @ GWBUF that is more convenient to
 | 
						|
 * use in a C++ context.
 | 
						|
 *
 | 
						|
 * As @c Buffer is a handle class, it should be created on the stack or as a
 | 
						|
 * member of an enclosing class, *never* dynamically.
 | 
						|
 *
 | 
						|
 * @c Buffer exposed _forward_ iterators to the underlying buffer that can
 | 
						|
 * be used in conjunction with standard C++ algorithms and functions.
 | 
						|
 */
 | 
						|
class Buffer
 | 
						|
{
 | 
						|
public:
 | 
						|
    // buf_type      : The type of the buffer, either "GWBUF*" or "const GWBUF*"
 | 
						|
    // pointer_type  : The type of a pointer to an element, either "uint8_t*" or "const uint8_t*".
 | 
						|
    // reference_type: The type of a reference to an element, either "uint8_t&" or "const uint8_t&".
 | 
						|
    template<class buf_type, class pointer_type, class reference_type>
 | 
						|
    class iterator_base : public std::iterator <
 | 
						|
        std::forward_iterator_tag, // The type of the iterator
 | 
						|
        uint8_t,                   // The type of the elems
 | 
						|
        std::ptrdiff_t,            // Difference between two its
 | 
						|
        pointer_type,              // The type of pointer to an elem
 | 
						|
        reference_type >           // The reference type of an elem
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        /**
 | 
						|
         * Returns address of the internal pointer to a GWBUF.
 | 
						|
         *
 | 
						|
         * @attention This is provided as a backdoor for situations where it is
 | 
						|
         *            unavoidable to access the interal pointer directly. It should
 | 
						|
         *            carefully be assessed whether it actually can be avoided.
 | 
						|
         *
 | 
						|
         * @return Pointer to pointer to GWBUF.
 | 
						|
         */
 | 
						|
        pointer_type* address_of()
 | 
						|
        {
 | 
						|
            return &m_i;
 | 
						|
        }
 | 
						|
 | 
						|
    protected:
 | 
						|
        iterator_base(buf_type pBuffer = NULL)
 | 
						|
            : m_pBuffer(pBuffer)
 | 
						|
            , m_i(m_pBuffer ? GWBUF_DATA(m_pBuffer) : NULL)
 | 
						|
            , m_end(m_pBuffer ? (m_i + GWBUF_LENGTH(m_pBuffer)) : NULL)
 | 
						|
        {}
 | 
						|
 | 
						|
        void advance()
 | 
						|
        {
 | 
						|
            ss_dassert(m_i != m_end);
 | 
						|
 | 
						|
            ++m_i;
 | 
						|
 | 
						|
            if (m_i == m_end)
 | 
						|
            {
 | 
						|
                m_pBuffer = m_pBuffer->next;
 | 
						|
 | 
						|
                if (m_pBuffer)
 | 
						|
                {
 | 
						|
                    m_i = GWBUF_DATA(m_pBuffer);
 | 
						|
                    m_end = m_i + GWBUF_LENGTH(m_pBuffer);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    m_i = NULL;
 | 
						|
                    m_end = NULL;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        bool eq(const iterator_base& rhs) const
 | 
						|
        {
 | 
						|
            return m_i == rhs.m_i;
 | 
						|
        }
 | 
						|
 | 
						|
        bool neq(const iterator_base& rhs) const
 | 
						|
        {
 | 
						|
            return !eq(rhs);
 | 
						|
        }
 | 
						|
 | 
						|
    protected:
 | 
						|
        buf_type     m_pBuffer;
 | 
						|
        pointer_type m_i;
 | 
						|
        pointer_type m_end;
 | 
						|
    };
 | 
						|
 | 
						|
    class const_iterator;
 | 
						|
 | 
						|
    // Buffer type, type of pointer to element and type of reference to element.
 | 
						|
    typedef iterator_base<GWBUF*, uint8_t*, uint8_t&> iterator_base_typedef;
 | 
						|
 | 
						|
    /**
 | 
						|
     * A forward iterator to Buffer.
 | 
						|
     */
 | 
						|
    class iterator : public iterator_base_typedef
 | 
						|
    {
 | 
						|
        friend class const_iterator;
 | 
						|
 | 
						|
    public:
 | 
						|
        explicit iterator(GWBUF* pBuffer = NULL)
 | 
						|
            : iterator_base_typedef(pBuffer)
 | 
						|
        {}
 | 
						|
 | 
						|
        iterator& operator++()
 | 
						|
        {
 | 
						|
            advance();
 | 
						|
            return *this;
 | 
						|
        }
 | 
						|
 | 
						|
        iterator operator++(int)
 | 
						|
        {
 | 
						|
            iterator rv(*this);
 | 
						|
            ++(*this);
 | 
						|
            return rv;
 | 
						|
        }
 | 
						|
 | 
						|
        bool operator == (const iterator& rhs) const
 | 
						|
        {
 | 
						|
            return eq(rhs);
 | 
						|
        }
 | 
						|
 | 
						|
        bool operator != (const iterator& rhs) const
 | 
						|
        {
 | 
						|
            return neq(rhs);
 | 
						|
        }
 | 
						|
 | 
						|
        reference operator*()
 | 
						|
        {
 | 
						|
            ss_dassert(m_i);
 | 
						|
            return *m_i;
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    // Buffer type, type of pointer to element and type of reference to element.
 | 
						|
    typedef iterator_base<const GWBUF*, const uint8_t*, const uint8_t&> const_iterator_base_typedef;
 | 
						|
 | 
						|
    /**
 | 
						|
     * A const forward iterator to Buffer.
 | 
						|
     */
 | 
						|
    class const_iterator : public const_iterator_base_typedef
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        explicit const_iterator(const GWBUF* pBuffer = NULL)
 | 
						|
            : const_iterator_base_typedef(pBuffer)
 | 
						|
        {}
 | 
						|
 | 
						|
        const_iterator(const Buffer::iterator& rhs)
 | 
						|
            : const_iterator_base_typedef(rhs.m_pBuffer)
 | 
						|
        {}
 | 
						|
 | 
						|
        const_iterator& operator++()
 | 
						|
        {
 | 
						|
            advance();
 | 
						|
            return *this;
 | 
						|
        }
 | 
						|
 | 
						|
        const_iterator operator++(int)
 | 
						|
        {
 | 
						|
            const_iterator rv(*this);
 | 
						|
            ++(*this);
 | 
						|
            return rv;
 | 
						|
        }
 | 
						|
 | 
						|
        bool operator == (const const_iterator& rhs) const
 | 
						|
        {
 | 
						|
            return eq(rhs);
 | 
						|
        }
 | 
						|
 | 
						|
        bool operator != (const const_iterator& rhs) const
 | 
						|
        {
 | 
						|
            return neq(rhs);
 | 
						|
        }
 | 
						|
 | 
						|
        reference operator*() const
 | 
						|
        {
 | 
						|
            ss_dassert(m_i);
 | 
						|
            return *m_i;
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates an empty buffer.
 | 
						|
     */
 | 
						|
    Buffer()
 | 
						|
        : m_pBuffer(NULL)
 | 
						|
    {}
 | 
						|
 | 
						|
    /**
 | 
						|
     * Copy constructor.
 | 
						|
     *
 | 
						|
     * @param rhs  The @c Buffer to copy.
 | 
						|
     *
 | 
						|
     * @throws @c std::bad_alloc if the underlying @c GWBUF cannot be cloned.
 | 
						|
     *
 | 
						|
     */
 | 
						|
    Buffer(const Buffer& rhs)
 | 
						|
    {
 | 
						|
        if (rhs.m_pBuffer)
 | 
						|
        {
 | 
						|
            m_pBuffer = gwbuf_clone(rhs.m_pBuffer);
 | 
						|
 | 
						|
            if (!m_pBuffer)
 | 
						|
            {
 | 
						|
                ss_dassert(!true);
 | 
						|
                throw std::bad_alloc();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            m_pBuffer = NULL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
#if __cplusplus >= 201103
 | 
						|
    /**
 | 
						|
     * Move constructor.
 | 
						|
     *
 | 
						|
     * @param rhs  The @c Buffer to be moved.
 | 
						|
     */
 | 
						|
    Buffer(Buffer&& rhs)
 | 
						|
        : m_pBuffer(NULL)
 | 
						|
    {
 | 
						|
        swap(rhs);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a @Buffer from a @ GWBUF
 | 
						|
     *
 | 
						|
     * @param pBuffer  The buffer to create the @c Buffer from.
 | 
						|
     *
 | 
						|
     * @attention  The ownership of @c pBuffer is transferred to the
 | 
						|
     *             @c Buffer being created.
 | 
						|
     */
 | 
						|
    Buffer(GWBUF* pBuffer)
 | 
						|
        : m_pBuffer(pBuffer)
 | 
						|
    {}
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a buffer of specified size.
 | 
						|
     *
 | 
						|
     * @param size  The size of the buffer.
 | 
						|
     *
 | 
						|
     * @attention  @c std::bad_alloc is thrown if the allocation fails.
 | 
						|
     */
 | 
						|
    Buffer(size_t size)
 | 
						|
        : m_pBuffer(gwbuf_alloc(size))
 | 
						|
    {
 | 
						|
        if (!m_pBuffer)
 | 
						|
        {
 | 
						|
            throw std::bad_alloc();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a buffer from existing data.
 | 
						|
     *
 | 
						|
     * @param pData  Pointer to data.
 | 
						|
     * @param size   The size of the data.
 | 
						|
     *
 | 
						|
     * @attention  @c std::bad_alloc is thrown if the allocation fails.
 | 
						|
     */
 | 
						|
    Buffer(const void* pData, size_t size)
 | 
						|
        : m_pBuffer(gwbuf_alloc_and_load(size, pData))
 | 
						|
    {
 | 
						|
        if (!m_pBuffer)
 | 
						|
        {
 | 
						|
            throw std::bad_alloc();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a buffer from a std::vector.
 | 
						|
     *
 | 
						|
     * @param data  The data to be copied.
 | 
						|
     *
 | 
						|
     * @attention  @c std::bad_alloc is thrown if the allocation fails.
 | 
						|
     */
 | 
						|
    Buffer(const std::vector<uint8_t>& data)
 | 
						|
        : m_pBuffer(gwbuf_alloc(data.size()))
 | 
						|
    {
 | 
						|
        if (m_pBuffer)
 | 
						|
        {
 | 
						|
            std::copy(data.begin(), data.end(), GWBUF_DATA(m_pBuffer));
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            throw std::bad_alloc();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Destructor
 | 
						|
     */
 | 
						|
    ~Buffer()
 | 
						|
    {
 | 
						|
        reset();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Assignment operator
 | 
						|
     *
 | 
						|
     * @param rhs  The @c Buffer to be assigned to this.
 | 
						|
     *
 | 
						|
     * @return this
 | 
						|
     *
 | 
						|
     * @attention  The @c Buffer provided as argument will be copied, which
 | 
						|
     *             may cause @c std::bad_alloc to be thrown.
 | 
						|
     *
 | 
						|
     * @attention  Does not invalidates iterators, but after the call, the iterators
 | 
						|
     *             will refer to the data of the other @c Buffer.
 | 
						|
     *
 | 
						|
     * @see Buffer::copy_from
 | 
						|
     */
 | 
						|
    Buffer& operator = (Buffer rhs)
 | 
						|
    {
 | 
						|
        swap(rhs);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
#if __cplusplus >= 201103
 | 
						|
    /**
 | 
						|
     * Move assignment operator
 | 
						|
     *
 | 
						|
     * @param rhs  The @c Buffer to be moves.
 | 
						|
     */
 | 
						|
    Buffer& operator = (Buffer&& rhs)
 | 
						|
    {
 | 
						|
        reset();
 | 
						|
        swap(rhs);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a forward iterator to the beginning of the Buffer.
 | 
						|
     *
 | 
						|
     * @return  A forward iterator.
 | 
						|
     */
 | 
						|
    iterator begin()
 | 
						|
    {
 | 
						|
        return iterator(m_pBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a forward iterator to the end of the Buffer.
 | 
						|
     *
 | 
						|
     * @return  A forward iterator.
 | 
						|
     */
 | 
						|
    iterator end()
 | 
						|
    {
 | 
						|
        return iterator();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a const forward iterator to the beginning of the Buffer.
 | 
						|
     *
 | 
						|
     * @return  A const forward iterator.
 | 
						|
     */
 | 
						|
    const_iterator begin() const
 | 
						|
    {
 | 
						|
        return const_iterator(m_pBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a const forward iterator to the end of the Buffer.
 | 
						|
     *
 | 
						|
     * @return  A const forward iterator.
 | 
						|
     */
 | 
						|
    const_iterator end() const
 | 
						|
    {
 | 
						|
        return const_iterator();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Swap the contents with another @c Buffer
 | 
						|
     *
 | 
						|
     * @param buffer  The @c Buffer to swap contents with.
 | 
						|
     */
 | 
						|
    void swap(Buffer& buffer)
 | 
						|
    {
 | 
						|
        GWBUF* pBuffer = buffer.m_pBuffer;
 | 
						|
        buffer.m_pBuffer = m_pBuffer;
 | 
						|
        m_pBuffer = pBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Clones the underlying @c GWBUF of the provided @c Buffer, and frees
 | 
						|
     * the current buffer. Effectively an assignment operator that does
 | 
						|
     * not throw.
 | 
						|
     *
 | 
						|
     * @param rhs  The @c Buffer to be copied.
 | 
						|
     *
 | 
						|
     * @return  True, if the buffer could be copied.
 | 
						|
     *
 | 
						|
     * @attention  Invalidates all iterators.
 | 
						|
     *
 | 
						|
     * @see Buffer::operator =
 | 
						|
     */
 | 
						|
    bool copy_from(const Buffer& rhs)
 | 
						|
    {
 | 
						|
        bool copied = true;
 | 
						|
        GWBUF* pBuffer = rhs.m_pBuffer;
 | 
						|
 | 
						|
        if (pBuffer)
 | 
						|
        {
 | 
						|
            GWBUF* pBuffer = gwbuf_clone(pBuffer);
 | 
						|
 | 
						|
            if (!pBuffer)
 | 
						|
            {
 | 
						|
                copied = false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (copied)
 | 
						|
        {
 | 
						|
            reset(pBuffer);
 | 
						|
        }
 | 
						|
 | 
						|
        return copied;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Compare content with another @ Buffer
 | 
						|
     *
 | 
						|
     * @param buffer  The buffer to compare with.
 | 
						|
     *
 | 
						|
     * @return  0 if identical,
 | 
						|
     *         -1 if this less that @c buffer, and
 | 
						|
     *         +1 if @c buffer less than this.
 | 
						|
     */
 | 
						|
    int compare(const Buffer& buffer) const
 | 
						|
    {
 | 
						|
        return gwbuf_compare(m_pBuffer, buffer.m_pBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Compare content with a @c GWBUF
 | 
						|
     *
 | 
						|
     * @param buffer  The buffer to compare with.
 | 
						|
     *
 | 
						|
     * @return  0 if identical,
 | 
						|
     *         -1 if this less that @c buffer, and
 | 
						|
     *         +1 if @c buffer less than this.
 | 
						|
     */
 | 
						|
    int compare(const GWBUF& buffer) const
 | 
						|
    {
 | 
						|
        return gwbuf_compare(m_pBuffer, &buffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Is content identical
 | 
						|
     *
 | 
						|
     * @param buffer  The buffer to compare with.
 | 
						|
     *
 | 
						|
     * @return True, if identical, otherwise false.
 | 
						|
     */
 | 
						|
    bool eq(const Buffer& buffer) const
 | 
						|
    {
 | 
						|
        return compare(buffer) == 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Is content identical.
 | 
						|
     *
 | 
						|
     * @param pBuffer  The buffer to compare with.
 | 
						|
     *
 | 
						|
     * @return True, if identical, otherwise false.
 | 
						|
     */
 | 
						|
    bool eq(const GWBUF& buffer) const
 | 
						|
    {
 | 
						|
        return compare(buffer) == 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Appends a @GWBUF to this.
 | 
						|
     *
 | 
						|
     * @param pBuffer  The buffer to be appended to this @c Buffer. Becomes
 | 
						|
     *                 the property of the buffer.
 | 
						|
     *
 | 
						|
     * @return this
 | 
						|
     *
 | 
						|
     * @attention  Does not invalidate any iterators, but an iterator
 | 
						|
     *             that has reached the end will remain there.
 | 
						|
     */
 | 
						|
    Buffer& append(GWBUF* pBuffer)
 | 
						|
    {
 | 
						|
        m_pBuffer = gwbuf_append(m_pBuffer, pBuffer);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Appends a @Buffer to this.
 | 
						|
     *
 | 
						|
     * @param buffer  The buffer to be appended to this Buffer.
 | 
						|
     *
 | 
						|
     * @return this
 | 
						|
     *
 | 
						|
     * @attention After the call, the @c Buffer provided as argument
 | 
						|
     *            will be empty.
 | 
						|
     *
 | 
						|
     * @attention  Does not invalidate any iterators, but an iterator
 | 
						|
     *             that has reached the end will remain there.
 | 
						|
     */
 | 
						|
    Buffer& append(Buffer& buffer)
 | 
						|
    {
 | 
						|
        m_pBuffer = gwbuf_append(m_pBuffer, buffer.release());
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the underlying GWBUF.
 | 
						|
     *
 | 
						|
     * @return  The underlying @c GWBUF.
 | 
						|
     *
 | 
						|
     * @attention This does not release ownership of the buffer. The returned pointer must never be
 | 
						|
     *            freed by the caller.
 | 
						|
     */
 | 
						|
    GWBUF* get()
 | 
						|
    {
 | 
						|
        return m_pBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Resets the underlying GWBUF.
 | 
						|
     *
 | 
						|
     * @param pBuffer  The @c GWBUF the @c Buffer should be reset with.
 | 
						|
     *
 | 
						|
     * @attention  The ownership of @c pBuffer is moved to the @c Buffer.
 | 
						|
     *
 | 
						|
     * @attention  Invalidates all iterators.
 | 
						|
     */
 | 
						|
    void reset(GWBUF* pBuffer = NULL)
 | 
						|
    {
 | 
						|
        gwbuf_free(m_pBuffer);
 | 
						|
        m_pBuffer = pBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Releases the underlying GWBUF.
 | 
						|
     *
 | 
						|
     * @return  The underlying @c GWBUF.
 | 
						|
     *
 | 
						|
     * @attention  The ownership of the buffer is transferred to the caller.
 | 
						|
     *
 | 
						|
     * @attention  Does not invalidate existing iterators, but any manipulation
 | 
						|
     *             of the returned @c GWBUF may invalidate them.
 | 
						|
     */
 | 
						|
    GWBUF* release()
 | 
						|
    {
 | 
						|
        GWBUF* pBuffer = m_pBuffer;
 | 
						|
        m_pBuffer = NULL;
 | 
						|
        return pBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the address of the underlying @ GWBUF. This is intended to only
 | 
						|
     * be used in a context where a function returns a @c GWBUF as an out argument.
 | 
						|
     * For instance:
 | 
						|
     *
 | 
						|
     *    void get_gwbuf(GWBUF** ppBuffer);
 | 
						|
     *    ...
 | 
						|
     *    Buffer buffer;
 | 
						|
     *
 | 
						|
     *    get_gwbuf(&buffer);
 | 
						|
     *
 | 
						|
     * @return  The address of the internal @c GWBUF pointer.
 | 
						|
     *
 | 
						|
     * @attention If the @c Buffer already refers to a @c GWBUF, that underlying
 | 
						|
     *            buffer will first be freed.
 | 
						|
     *
 | 
						|
     * @attention Invalidates all iterators.
 | 
						|
     */
 | 
						|
    GWBUF** operator & ()
 | 
						|
    {
 | 
						|
        reset();
 | 
						|
        return &m_pBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The total length of the buffer.
 | 
						|
     *
 | 
						|
     * @return The total length of the buffer.
 | 
						|
     */
 | 
						|
    size_t length() const
 | 
						|
    {
 | 
						|
        return gwbuf_length(m_pBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Whether the buffer is contiguous.
 | 
						|
     *
 | 
						|
     * @return  True, if the buffer is contiguous.
 | 
						|
     */
 | 
						|
    bool is_contiguous() const
 | 
						|
    {
 | 
						|
        return GWBUF_IS_CONTIGUOUS(m_pBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Make the buffer contiguous.
 | 
						|
     *
 | 
						|
     * @return  True, if the buffer could be made contiguous.
 | 
						|
     *
 | 
						|
     * @attention  Invalidates all iterators.
 | 
						|
     */
 | 
						|
    bool make_contiguous(std::nothrow_t)
 | 
						|
    {
 | 
						|
        GWBUF* pBuffer = gwbuf_make_contiguous(m_pBuffer);
 | 
						|
 | 
						|
        if (pBuffer)
 | 
						|
        {
 | 
						|
            m_pBuffer = pBuffer;
 | 
						|
        }
 | 
						|
 | 
						|
        return pBuffer != NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Make the buffer contiguous.
 | 
						|
     *
 | 
						|
     * @throws  @c std::bad_alloc if an allocation failed.
 | 
						|
     *
 | 
						|
     * @attention  Invalidates all iterators.
 | 
						|
     */
 | 
						|
    void make_contiguous()
 | 
						|
    {
 | 
						|
        if (!make_contiguous(std::nothrow))
 | 
						|
        {
 | 
						|
            ss_dassert(!true);
 | 
						|
            throw std::bad_alloc();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    // To prevent @c Buffer from being created on the heap.
 | 
						|
    void* operator new(size_t);          // standard new
 | 
						|
    void* operator new(size_t, void*);   // placement new
 | 
						|
    void* operator new[](size_t);        // array new
 | 
						|
    void* operator new[](size_t, void*); // placement array new
 | 
						|
 | 
						|
private:
 | 
						|
    GWBUF* m_pBuffer;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Checks two @c Buffers for equality.
 | 
						|
 *
 | 
						|
 * @return True if equal, false otherwise.
 | 
						|
 */
 | 
						|
inline bool operator == (const Buffer& lhs, const Buffer& rhs)
 | 
						|
{
 | 
						|
    return lhs.eq(rhs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Checks a @c Buffer and a @c GWBUF for equality.
 | 
						|
 *
 | 
						|
 * @return True if equal, false otherwise.
 | 
						|
 */
 | 
						|
inline bool operator == (const Buffer& lhs, const GWBUF& rhs)
 | 
						|
{
 | 
						|
    return lhs.eq(rhs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Checks two @c Buffers for un-equality.
 | 
						|
 *
 | 
						|
 * @return True if un-equal, false otherwise.
 | 
						|
 */
 | 
						|
inline bool operator != (const Buffer& lhs, const Buffer& rhs)
 | 
						|
{
 | 
						|
    return !lhs.eq(rhs);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Checks a @c Buffer and a @c GWBUF for un-equality.
 | 
						|
 *
 | 
						|
 * @return True if un-equal, false otherwise.
 | 
						|
 */
 | 
						|
inline bool operator != (const Buffer& lhs, const GWBUF& rhs)
 | 
						|
{
 | 
						|
    return !lhs.eq(rhs);
 | 
						|
}
 | 
						|
 | 
						|
}
 |