FieldMap.h
Go to the documentation of this file.
/* -*- C++ -*- */
/****************************************************************************
** Copyright (c) 2001-2014
**
** This file is part of the QuickFIX FIX Engine
**
** This file may be distributed under the terms of the quickfixengine.org
** license as defined by quickfixengine.org and appearing in the file
** LICENSE included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.quickfixengine.org/LICENSE for licensing information.
**
** Contact ask@quickfixengine.org if any conditions of this licensing are
** not clear to you.
**
****************************************************************************/
#ifndef FIX_FIELDMAP
#define FIX_FIELDMAP
#ifdef _MSC_VER
#pragma warning( disable: 4786 )
#endif
#include "Field.h"
#include "MessageSorters.h"
#include "Exceptions.h"
#include "Utility.h"
#include <map>
#include <vector>
#include <sstream>
#include <algorithm>
namespace FIX
{
class FieldMap
{
class sorter
{
public:
explicit sorter( const message_order& order ) : m_order( order ) {}
bool operator()( int tag, const FieldBase& right ) const
{
return m_order( tag, right.getTag() );
}
bool operator()( const FieldBase& left, int tag ) const
{
return m_order( left.getTag(), tag );
}
bool operator()( const FieldBase& left, const FieldBase& right ) const
{
return m_order( left.getTag(), right.getTag() );
}
private:
const message_order& m_order;
};
class finder
{
public:
explicit finder( int tag ) : m_tag( tag ) {}
bool operator()( const FieldBase& field ) const
{
return m_tag == field.getTag();
}
private:
int m_tag;
};
enum { DEFAULT_SIZE = 16 };
protected:
FieldMap( const message_order& order, int size );
public:
typedef std::vector < FieldBase, ALLOCATOR< FieldBase > > Fields;
typedef std::map < int, std::vector < FieldMap* >, std::less<int>,
ALLOCATOR<std::pair<const int, std::vector< FieldMap* > > > > Groups;
typedef Fields::iterator iterator;
typedef Fields::const_iterator const_iterator;
typedef Groups::iterator g_iterator;
typedef Groups::const_iterator g_const_iterator;
FieldMap( const message_order& order =
message_order( message_order::normal ) );
FieldMap( const int order[] );
FieldMap( const FieldMap& copy );
virtual ~FieldMap();
FieldMap& operator=( const FieldMap& rhs );
void setField( const FieldBase& field, bool overwrite = true )
throw( RepeatedTag )
{
if( !overwrite )
{
addField( field );
}
else
{
Fields::iterator i = findTag( field.getTag() );
if( i == m_fields.end() )
{
addField( field );
}
else
{
i->setString( field.getString() );
}
}
}
void setField( int tag, const std::string& value )
throw( RepeatedTag, NoTagValue )
{
FieldBase fieldBase( tag, value );
setField( fieldBase );
}
bool getFieldIfSet( FieldBase& field ) const
{
Fields::const_iterator iter = findTag( field.getTag() );
if ( iter == m_fields.end() )
return false;
field = (*iter);
return true;
}
FieldBase& getField( FieldBase& field )
const throw( FieldNotFound )
{
field = getFieldRef( field.getTag() );
return field;
}
const std::string& getField( int tag )
const throw( FieldNotFound )
{
return getFieldRef( tag ).getString();
}
const FieldBase& getFieldRef( int tag )
const throw( FieldNotFound )
{
Fields::const_iterator iter = findTag( tag );
if ( iter == m_fields.end() )
throw FieldNotFound( tag );
return (*iter);
}
const FieldBase* const getFieldPtr( int tag )
const throw( FieldNotFound )
{
return &getFieldRef( tag );
}
bool isSetField( const FieldBase& field ) const
{ return isSetField( field.getTag() ); }
bool isSetField( int tag ) const
{ return findTag( tag ) != m_fields.end(); }
void removeField( int tag );
void addGroup( int tag, const FieldMap& group, bool setCount = true );
void addGroupPtr( int tag, FieldMap * group, bool setCount = true );
void replaceGroup( int num, int tag, const FieldMap& group );
FieldMap& getGroup( int num, int tag, FieldMap& group ) const
throw( FieldNotFound )
{
return group = getGroupRef( num, tag );
}
FieldMap& getGroupRef( int num, int tag ) const
throw( FieldNotFound )
{
Groups::const_iterator i = m_groups.find( tag );
if( i == m_groups.end() ) throw FieldNotFound( tag );
if( num <= 0 ) throw FieldNotFound( tag );
if( i->second.size() < (unsigned)num ) throw FieldNotFound( tag );
return *( *(i->second.begin() + (num-1) ) );
}
FieldMap* getGroupPtr( int num, int tag ) const
throw( FieldNotFound )
{
return &getGroupRef( num, tag );
}
void removeGroup( int num, int tag );
void removeGroup( int tag );
bool hasGroup( int tag ) const;
bool hasGroup( int num, int tag ) const;
size_t groupCount( int tag ) const;
void clear();
bool isEmpty();
size_t totalFields() const;
std::string& calculateString( std::string& ) const;
int calculateLength( int beginStringField = FIELD::BeginString,
int bodyLengthField = FIELD::BodyLength,
int checkSumField = FIELD::CheckSum ) const;
int calculateTotal( int checkSumField = FIELD::CheckSum ) const;
iterator begin() { return m_fields.begin(); }
iterator end() { return m_fields.end(); }
const_iterator begin() const { return m_fields.begin(); }
const_iterator end() const { return m_fields.end(); }
g_iterator g_begin() { return m_groups.begin(); }
g_iterator g_end() { return m_groups.end(); }
g_const_iterator g_begin() const { return m_groups.begin(); }
g_const_iterator g_end() const { return m_groups.end(); }
protected:
friend class Message;
void addField( const FieldBase& field )
{
Fields::iterator iter = findPositionFor( field.getTag() );
if( iter == m_fields.end() )
{
m_fields.push_back( field );
}
else
{
m_fields.insert( iter, field );
}
}
// used to find data length fields during message decoding
// message fields are not yet sorted so regular find*** functions might return wrong results
const FieldBase& reverse_find( int tag ) const
{
Fields::const_reverse_iterator iter = std::find_if( m_fields.rbegin(), m_fields.rend(), finder( tag ) );
if( iter == m_fields.rend() )
throw FieldNotFound( tag );
return *iter;
}
// append field to message without sorting
// only applicable during message decoding
void appendField( const FieldBase& field )
{
m_fields.push_back( field );
}
// sort fields after message decoding
void sortFields()
{
std::sort( m_fields.begin(), m_fields.end(), sorter(m_order) );
}
private:
Fields::const_iterator findTag( int tag ) const
{
return lookup( m_fields.begin(), m_fields.end(), tag );
}
Fields::iterator findTag( int tag )
{
return lookup( m_fields.begin(), m_fields.end(), tag );
}
template <typename Iterator>
Iterator lookup(Iterator begin, Iterator end, int tag) const
{
#if defined(__SUNPRO_CC)
std::size_t numElements;
std::distance( begin, end, numElements );
#else
std::size_t numElements = std::distance( begin, end );
#endif
if( numElements < 16 )
return std::find_if( begin, end, finder( tag ) );
Iterator iter = std::lower_bound( begin, end, tag, sorter( m_order ) );
if( iter != end &&
iter->getTag() == tag )
{
return iter;
}
return end;
}
Fields::iterator findPositionFor( int tag )
{
if( m_fields.empty() )
return m_fields.end();
const FieldBase& last = m_fields.back();
if( m_order( last.getTag(), tag ) ||
last.getTag() == tag )
{
return m_fields.end();
}
return std::upper_bound( m_fields.begin(), m_fields.end(), tag, sorter( m_order ) );
}
Fields m_fields;
Groups m_groups;
message_order m_order;
};
}
#define FIELD_SET( MAP, FIELD ) \
bool isSet( const FIELD& field ) const \
{ return (MAP).isSetField(field); } \
void set( const FIELD& field ) \
{ (MAP).setField(field); } \
FIELD& get( FIELD& field ) const \
{ return (FIELD&)(MAP).getField(field); } \
bool getIfSet( FIELD& field ) const \
{ return (MAP).getFieldIfSet(field); }
#define FIELD_GET_PTR( MAP, FLD ) \
(const FIX::FLD*)MAP.getFieldPtr( FIX::FIELD::FLD )
#define FIELD_GET_REF( MAP, FLD ) \
(const FIX::FLD&)MAP.getFieldRef( FIX::FIELD::FLD )
#define FIELD_THROW_IF_NOT_FOUND( MAP, FLD ) \
if( !(MAP).isSetField( FIX::FIELD::FLD) ) \
throw FieldNotFound( FIX::FIELD::FLD )
#endif //FIX_FIELDMAP
Exceptions.h
Field.h
MessageSorters.h
Utility.h
FIX::FieldBase
Base representation of all Field classes.
Definition: Field.h:50
FIX::FieldBase::getTag
int getTag() const
Get the fields integer tag.
Definition: Field.h:144
FIX::FieldBase::getString
const std::string & getString() const
Get the string representation of the fields value.
Definition: Field.h:152
FIX::FieldMap::finder
Definition: FieldMap.h:74
FIX::FieldMap::finder::finder
finder(int tag)
Definition: FieldMap.h:76
FIX::FieldMap::finder::m_tag
int m_tag
Definition: FieldMap.h:84
FIX::FieldMap::finder::operator()
bool operator()(const FieldBase &field) const
Definition: FieldMap.h:78
FIX::FieldMap::sorter
Definition: FieldMap.h:50
FIX::FieldMap::sorter::m_order
const message_order & m_order
Definition: FieldMap.h:70
FIX::FieldMap::sorter::sorter
sorter(const message_order &order)
Definition: FieldMap.h:52
FIX::FieldMap::sorter::operator()
bool operator()(int tag, const FieldBase &right) const
Definition: FieldMap.h:54
FIX::FieldMap::sorter::operator()
bool operator()(const FieldBase &left, int tag) const
Definition: FieldMap.h:59
FIX::FieldMap::sorter::operator()
bool operator()(const FieldBase &left, const FieldBase &right) const
Definition: FieldMap.h:64
FIX::FieldMap
Stores and organizes a collection of Fields.
Definition: FieldMap.h:47
FIX::FieldMap::Fields
std::vector< FieldBase, ALLOCATOR< FieldBase > > Fields
Definition: FieldMap.h:95
FIX::FieldMap::setField
void setField(const FieldBase &field, bool overwrite=true)
Set a field without type checking.
Definition: FieldMap.h:116
FIX::FieldMap::replaceGroup
void replaceGroup(int num, int tag, const FieldMap &group)
Replace a specific instance of a group.
Definition: FieldMap.cpp:102
FIX::FieldMap::sortFields
void sortFields()
Definition: FieldMap.h:303
FIX::FieldMap::getGroupRef
FieldMap & getGroupRef(int num, int tag) const
Get direct access to a field through a reference.
Definition: FieldMap.h:214
FIX::FieldMap::addField
void addField(const FieldBase &field)
Definition: FieldMap.h:271
FIX::FieldMap::getField
FieldBase & getField(FieldBase &field) const
Get a field without type checking.
Definition: FieldMap.h:156
FIX::FieldMap::iterator
Fields::iterator iterator
Definition: FieldMap.h:99
FIX::FieldMap::isEmpty
bool isEmpty()
Check if map contains any fields.
Definition: FieldMap.cpp:196
FIX::FieldMap::begin
iterator begin()
Definition: FieldMap.h:258
FIX::FieldMap::appendField
void appendField(const FieldBase &field)
Definition: FieldMap.h:297
FIX::FieldMap::g_iterator
Groups::iterator g_iterator
Definition: FieldMap.h:101
FIX::FieldMap::g_begin
g_iterator g_begin()
Definition: FieldMap.h:262
FIX::FieldMap::findTag
Fields::const_iterator findTag(int tag) const
Definition: FieldMap.h:310
FIX::FieldMap::calculateLength
int calculateLength(int beginStringField=FIELD::BeginString, int bodyLengthField=FIELD::BodyLength, int checkSumField=FIELD::CheckSum) const
Definition: FieldMap.cpp:233
FIX::FieldMap::removeField
void removeField(int tag)
Remove a field. If field is not present, this is a no-op.
Definition: FieldMap.cpp:156
FIX::FieldMap::end
const_iterator end() const
Definition: FieldMap.h:261
FIX::FieldMap::Groups
std::map< int, std::vector< FieldMap * >, std::less< int >, ALLOCATOR< std::pair< const int, std::vector< FieldMap * > > > > Groups
Definition: FieldMap.h:97
FIX::FieldMap::lookup
Iterator lookup(Iterator begin, Iterator end, int tag) const
Definition: FieldMap.h:321
FIX::FieldMap::g_const_iterator
Groups::const_iterator g_const_iterator
Definition: FieldMap.h:102
FIX::FieldMap::getFieldPtr
const FieldBase *const getFieldPtr(int tag) const
Get direct access to a field through a pointer.
Definition: FieldMap.h:181
FIX::FieldMap::g_end
g_const_iterator g_end() const
Definition: FieldMap.h:265
FIX::FieldMap::end
iterator end()
Definition: FieldMap.h:259
FIX::FieldMap::DEFAULT_SIZE
@ DEFAULT_SIZE
Definition: FieldMap.h:87
FIX::FieldMap::getField
const std::string & getField(int tag) const
Get a field without a field class.
Definition: FieldMap.h:164
FIX::FieldMap::getGroupPtr
FieldMap * getGroupPtr(int num, int tag) const
Get direct access to a field through a pointer.
Definition: FieldMap.h:225
FIX::FieldMap::clear
void clear()
Clear all fields from the map.
Definition: FieldMap.cpp:182
FIX::FieldMap::m_order
message_order m_order
Definition: FieldMap.h:359
FIX::FieldMap::setField
void setField(int tag, const std::string &value)
Set a field without a field class.
Definition: FieldMap.h:138
FIX::FieldMap::m_groups
Groups m_groups
Definition: FieldMap.h:358
FIX::FieldMap::hasGroup
bool hasGroup(int tag) const
Check to see any instance of a group exists.
Definition: FieldMap.cpp:168
FIX::FieldMap::addGroupPtr
void addGroupPtr(int tag, FieldMap *group, bool setCount=true)
Acquire ownership of Group object.
Definition: FieldMap.cpp:90
FIX::FieldMap::getFieldIfSet
bool getFieldIfSet(FieldBase &field) const
Get a field if set.
Definition: FieldMap.h:146
FIX::FieldMap::const_iterator
Fields::const_iterator const_iterator
Definition: FieldMap.h:100
FIX::FieldMap::FieldMap
FieldMap(const message_order &order, int size)
Definition: FieldMap.cpp:34
FIX::FieldMap::calculateString
std::string & calculateString(std::string &) const
Definition: FieldMap.cpp:215
FIX::FieldMap::findPositionFor
Fields::iterator findPositionFor(int tag)
Definition: FieldMap.h:342
FIX::FieldMap::~FieldMap
virtual ~FieldMap()
Definition: FieldMap.cpp:57
FIX::FieldMap::begin
const_iterator begin() const
Definition: FieldMap.h:260
FIX::FieldMap::g_end
g_iterator g_end()
Definition: FieldMap.h:263
FIX::FieldMap::getGroup
FieldMap & getGroup(int num, int tag, FieldMap &group) const
Get a specific instance of a group.
Definition: FieldMap.h:207
FIX::FieldMap::addGroup
void addGroup(int tag, const FieldMap &group, bool setCount=true)
Add a group.
Definition: FieldMap.cpp:83
FIX::FieldMap::reverse_find
const FieldBase & reverse_find(int tag) const
Definition: FieldMap.h:286
FIX::FieldMap::operator=
FieldMap & operator=(const FieldMap &rhs)
Definition: FieldMap.cpp:62
FIX::FieldMap::calculateTotal
int calculateTotal(int checkSumField=FIELD::CheckSum) const
Definition: FieldMap.cpp:258
FIX::FieldMap::totalFields
size_t totalFields() const
Definition: FieldMap.cpp:201
FIX::FieldMap::m_fields
Fields m_fields
Definition: FieldMap.h:357
FIX::FieldMap::removeGroup
void removeGroup(int num, int tag)
Remove a specific instance of a group.
Definition: FieldMap.cpp:111
FIX::FieldMap::isSetField
bool isSetField(const FieldBase &field) const
Check to see if a field is set.
Definition: FieldMap.h:188
FIX::FieldMap::getFieldRef
const FieldBase & getFieldRef(int tag) const
Get direct access to a field through a reference.
Definition: FieldMap.h:171
FIX::FieldMap::isSetField
bool isSetField(int tag) const
Check to see if a field is set by referencing its number.
Definition: FieldMap.h:191
FIX::FieldMap::groupCount
size_t groupCount(int tag) const
Count the number of instance of a group.
Definition: FieldMap.cpp:174
FIX::FieldMap::g_begin
g_const_iterator g_begin() const
Definition: FieldMap.h:264
FIX::FieldMap::findTag
Fields::iterator findTag(int tag)
Definition: FieldMap.h:315
FIX::Message
Base class for all FIX messages.
Definition: Message.h:118
FIX
Definition: Acceptor.cpp:35
sort
void sort(I begin, I end, const Pred &pred)
Definition: pugixml.cpp:6153
FIX::FieldNotFound
Field not found inside a message.
Definition: Exceptions.h:58
FIX::NoTagValue
Field exists in message without a value.
Definition: Exceptions.h:129
FIX::RepeatedTag
Repeated tag not part of repeating group.
Definition: Exceptions.h:200
FIX::message_order
Sorts fields in header, normal, or trailer order.
Definition: MessageSorters.h:114
FIX::message_order::normal
@ normal
Definition: MessageSorters.h:116