336 lines
8.7 KiB
C++
336 lines
8.7 KiB
C++
// file : xsd/cxx/tree/buffer.hxx
|
|
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @brief Contains a simple binary buffer abstraction that is used to
|
|
* implement the base64Binary and hexBinary XML Schema built-in types.
|
|
*
|
|
* This is an internal header and is included by the generated code. You
|
|
* normally should not include it directly.
|
|
*
|
|
*/
|
|
|
|
#ifndef XSD_CXX_TREE_BUFFER_HXX
|
|
#define XSD_CXX_TREE_BUFFER_HXX
|
|
|
|
#include <new> // operator new/delete
|
|
#include <cstddef> // std::size_t
|
|
#include <cstring> // std::memcpy, std::memcmp
|
|
|
|
#include <xsd/cxx/tree/exceptions.hxx>
|
|
|
|
namespace xsd
|
|
{
|
|
namespace cxx
|
|
{
|
|
/**
|
|
* @brief C++/Tree mapping runtime namespace.
|
|
*
|
|
* This is an internal namespace and normally should not be referenced
|
|
* directly. Instead you should use the aliases for types in this
|
|
* namespaces that are created in the generated code.
|
|
*
|
|
*/
|
|
namespace tree
|
|
{
|
|
//@cond
|
|
|
|
class buffer_base
|
|
{
|
|
protected:
|
|
virtual
|
|
~buffer_base ()
|
|
{
|
|
if (free_ && data_)
|
|
operator delete (data_);
|
|
}
|
|
|
|
buffer_base ()
|
|
: data_ (0), size_ (0), capacity_ (0), free_ (true)
|
|
{
|
|
}
|
|
|
|
protected:
|
|
char* data_;
|
|
size_t size_;
|
|
size_t capacity_;
|
|
bool free_;
|
|
};
|
|
|
|
//@endcond
|
|
|
|
/**
|
|
* @brief Simple binary %buffer abstraction
|
|
*
|
|
* The %buffer class manages a continuous binary %buffer. The base
|
|
* concepts are data (actual memory region), size (the portion of
|
|
* the %buffer that contains useful information), and capacity (the
|
|
* actual size of the underlying memory region). The bounds
|
|
* %exception is thrown from the constructors and modifier functions
|
|
* if the (size <= capacity) constraint is violated.
|
|
*
|
|
* Note that the template parameter is only used to instantiate
|
|
* %exception types. The underlying %buffer type is always @c char.
|
|
*
|
|
* @nosubgrouping
|
|
*/
|
|
template<typename C>
|
|
class buffer: protected buffer_base
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Size type
|
|
*/
|
|
typedef std::size_t size_t;
|
|
|
|
public:
|
|
/**
|
|
* @name Constructors
|
|
*/
|
|
//@{
|
|
|
|
/**
|
|
* @brief Allocate a %buffer of the specified size.
|
|
*
|
|
* The resulting %buffer has the same size and capacity.
|
|
*
|
|
* @param size A %buffer size in bytes.
|
|
*/
|
|
explicit
|
|
buffer (size_t size = 0);
|
|
|
|
/**
|
|
* @brief Allocate a %buffer of the specified size and capacity.
|
|
*
|
|
* @param size A %buffer size in bytes.
|
|
* @param capacity A %buffer capacity in bytes.
|
|
* @throw bounds If @a size exceeds @a capacity
|
|
*/
|
|
buffer (size_t size, size_t capacity);
|
|
|
|
/**
|
|
* @brief Allocate a %buffer of the specified size and copy
|
|
* the data.
|
|
*
|
|
* The resulting %buffer has the same size and capacity with
|
|
* @a size bytes copied from @a data.
|
|
*
|
|
* @param data A %buffer to copy the data from.
|
|
* @param size A %buffer size in bytes.
|
|
*/
|
|
buffer (const void* data, size_t size);
|
|
|
|
/**
|
|
* @brief Allocate a %buffer of the specified size and capacity
|
|
* and copy the data.
|
|
*
|
|
* @a size bytes are copied from @a data to the resulting
|
|
* %buffer.
|
|
*
|
|
* @param data A %buffer to copy the data from.
|
|
* @param size A %buffer size in bytes.
|
|
* @param capacity A %buffer capacity in bytes.
|
|
* @throw bounds If @a size exceeds @a capacity
|
|
*/
|
|
buffer (const void* data, size_t size, size_t capacity);
|
|
|
|
/**
|
|
* @brief Reuse an existing %buffer.
|
|
*
|
|
* If the @a assume_ownership argument is true, the %buffer will
|
|
* assume ownership of @a data and will release the memory
|
|
* by calling @c operator @c delete().
|
|
*
|
|
* @param data A %buffer to reuse.
|
|
* @param size A %buffer size in bytes.
|
|
* @param capacity A %buffer capacity in bytes.
|
|
* @param assume_ownership A boolean value indication whether to
|
|
* assume ownership.
|
|
* @throw bounds If @a size exceeds @a capacity
|
|
*/
|
|
buffer (void* data,
|
|
size_t size,
|
|
size_t capacity,
|
|
bool assume_ownership);
|
|
|
|
/**
|
|
* @brief Copy constructor.
|
|
*
|
|
* The copy constructor performs a deep copy of the underlying
|
|
* memory %buffer.
|
|
*
|
|
* @param x An instance to make a copy of.
|
|
*/
|
|
buffer (const buffer& x);
|
|
|
|
//@}
|
|
|
|
public:
|
|
/**
|
|
* @brief Copy assignment operator.
|
|
*
|
|
* The copy assignment operator changes the buffer's capacity
|
|
* to @c x.capacity() and copies @c x.size() bytes from @a x.
|
|
*
|
|
* @param x An instance to assign.
|
|
* @return A reference to the instance.
|
|
*/
|
|
buffer&
|
|
operator= (const buffer& x);
|
|
|
|
public:
|
|
/**
|
|
* @brief Get buffer's capacity.
|
|
*
|
|
* @return A number of bytes that the %buffer can hold without
|
|
* reallocation.
|
|
*/
|
|
size_t
|
|
capacity () const
|
|
{
|
|
return capacity_;
|
|
}
|
|
|
|
/**
|
|
* @brief Set buffer's capacity.
|
|
*
|
|
* @param c The new capacity in bytes.
|
|
* @return True if the underlying %buffer has moved, false otherwise.
|
|
*/
|
|
bool
|
|
capacity (size_t c)
|
|
{
|
|
return this->capacity (c, true);
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @brief Get buffer's size.
|
|
*
|
|
* @return A number of bytes that the %buffer holds.
|
|
*/
|
|
size_t
|
|
size () const {return size_;}
|
|
|
|
/**
|
|
* @brief Set buffer's size.
|
|
*
|
|
* @param s The new size in bytes.
|
|
* @return True if the underlying %buffer has moved, false otherwise.
|
|
*/
|
|
bool
|
|
size (size_t s)
|
|
{
|
|
bool r (false);
|
|
|
|
if (s > capacity_)
|
|
r = capacity (s);
|
|
|
|
size_ = s;
|
|
|
|
return r;
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @brief Get the underlying memory region.
|
|
*
|
|
* @return A constant pointer to the underlying memory region.
|
|
*/
|
|
const char*
|
|
data () const {return data_;}
|
|
|
|
/**
|
|
* @brief Get the underlying memory region.
|
|
*
|
|
* @return A pointer to the underlying memory region.
|
|
*/
|
|
char*
|
|
data () {return data_;}
|
|
|
|
/**
|
|
* @brief Get the beginning of the underlying memory region.
|
|
*
|
|
* @return A constant pointer to the first byte of the underlying
|
|
* memory region.
|
|
*/
|
|
const char*
|
|
begin () const {return data_;}
|
|
|
|
/**
|
|
* @brief Get the beginning of the underlying memory region.
|
|
*
|
|
* @return A pointer to the first byte of the underlying memory
|
|
* region.
|
|
*/
|
|
char*
|
|
begin () {return data_;}
|
|
|
|
/**
|
|
* @brief Get the end of the underlying memory region.
|
|
*
|
|
* @return A constant pointer to the one past last byte of the
|
|
* underlying memory region (that is @c %begin() @c + @c %size() ).
|
|
*/
|
|
const char*
|
|
end () const {return data_ + size_;}
|
|
|
|
/**
|
|
* @brief Get the end of the underlying memory region.
|
|
*
|
|
* @return A pointer to the one past last byte of the underlying
|
|
* memory region (that is @c %begin() @c + @c %size() ).
|
|
*/
|
|
char*
|
|
end () {return data_ + size_;}
|
|
|
|
public:
|
|
/**
|
|
* @brief Swap data with another %buffer.
|
|
*
|
|
* @param x A %buffer to swap with.
|
|
*/
|
|
void
|
|
swap (buffer& x);
|
|
|
|
private:
|
|
bool
|
|
capacity (size_t capacity, bool copy);
|
|
};
|
|
|
|
/**
|
|
* @brief %buffer comparison operator.
|
|
*
|
|
* @return True if the buffers have the same sizes and the same
|
|
* data.
|
|
*/
|
|
template <typename C>
|
|
inline bool
|
|
operator== (const buffer<C>& a, const buffer<C>& b)
|
|
{
|
|
return a.size () == b.size () &&
|
|
std::memcmp (a.data (), b.data (), a.size ()) == 0;
|
|
}
|
|
|
|
/**
|
|
* @brief %buffer comparison operator.
|
|
*
|
|
* @return True if the buffers have different sizes or different
|
|
* data.
|
|
*/
|
|
template <typename C>
|
|
inline bool
|
|
operator!= (const buffer<C>& a, const buffer<C>& b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#include <xsd/cxx/tree/buffer.txx>
|
|
|
|
#endif // XSD_CXX_TREE_BUFFER_HXX
|