poco/Data/include/Poco/Data/Column.h
Roger Meier b0581433a7 LICENSE: add info about SPDX-License-Identifier usage and use it
fix: remove executable flag and change back to 100644 (was 100755)

Signed-off-by: Roger Meier <r.meier@siemens.com>
2014-05-14 08:38:09 +02:00

493 lines
9.8 KiB
C++

//
// Column.h
//
// $Id: //poco/Main/Data/include/Poco/Data/Column.h#5 $
//
// Library: Data
// Package: DataCore
// Module: Column
//
// Definition of the Column class.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_Column_INCLUDED
#define Data_Column_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/MetaColumn.h"
#include "Poco/SharedPtr.h"
#include "Poco/RefCountedObject.h"
#include <vector>
#include <list>
#include <deque>
namespace Poco {
namespace Data {
template <class C>
class Column
/// Column class is column data container.
/// Data (a pointer to underlying STL container) is assigned to the class
/// at construction time. Construction with null pointer is not allowed.
/// This class owns the data assigned to it and deletes the storage on destruction.
{
public:
typedef C Container;
typedef Poco::SharedPtr<C> ContainerPtr;
typedef typename C::const_iterator Iterator;
typedef typename C::const_reverse_iterator RIterator;
typedef typename C::size_type Size;
typedef typename C::value_type Type;
Column(const MetaColumn& metaColumn, Container* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
if (!_pData)
throw NullPointerException("Container pointer must point to valid storage.");
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
const Type& value(std::size_t row) const
/// Returns the field value in specified row.
{
try
{
return _pData->at(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
const Type& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
};
template <>
class Column<std::vector<bool> >
/// The std::vector<bool> specialization for the Column class.
///
/// This specialization is necessary due to the nature of std::vector<bool>.
/// For details, see the standard library implementation of vector<bool>
/// or
/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
/// Item 18: "Avoid using vector<bool>."
///
/// The workaround employed here is using deque<bool> as an
/// internal "companion" container kept in sync with the vector<bool>
/// column data.
{
public:
typedef std::vector<bool> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef Container::const_iterator Iterator;
typedef Container::const_reverse_iterator RIterator;
typedef Container::size_type Size;
Column(const MetaColumn& metaColumn, Container* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
poco_check_ptr (_pData);
_deque.assign(_pData->begin(), _pData->end());
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
_deque.assign(_pData->begin(), _pData->end());
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
swap(_deque, other._deque);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
const bool& value(std::size_t row) const
/// Returns the field value in specified row.
{
if (_deque.size() < _pData->size())
_deque.resize(_pData->size());
try
{
return _deque.at(row) = _pData->at(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
const bool& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
_deque.clear();
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
mutable std::deque<bool> _deque;
};
template <class T>
class Column<std::list<T> >
/// Column specialization for std::list
{
public:
typedef std::list<T> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef typename Container::const_iterator Iterator;
typedef typename Container::const_reverse_iterator RIterator;
typedef typename Container::size_type Size;
Column(const MetaColumn& metaColumn, std::list<T>* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
poco_check_ptr (_pData);
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
const T& value(std::size_t row) const
/// Returns the field value in specified row.
/// This is the std::list specialization and std::list
/// is not the optimal solution for cases where random
/// access is needed.
/// However, to allow for compatibility with other
/// containers, this functionality is provided here.
/// To alleviate the problem, an effort is made
/// to start iteration from beginning or end,
/// depending on the position requested.
{
if (row <= (std::size_t) (_pData->size() / 2))
{
Iterator it = _pData->begin();
Iterator end = _pData->end();
for (int i = 0; it != end; ++it, ++i)
if (i == row) return *it;
}
else
{
row = _pData->size() - row;
RIterator it = _pData->rbegin();
RIterator end = _pData->rend();
for (int i = 1; it != end; ++it, ++i)
if (i == row) return *it;
}
throw RangeException("Invalid row number.");
}
const T& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears the storage.
{
_pData->clear();
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
};
template <typename C>
inline void swap(Column<C>& c1, Column<C>& c2)
{
c1.swap(c2);
}
} } // namespace Poco::Data
#endif // Data_Column_INCLUDED