FieldMap.h
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 
3 /****************************************************************************
4 ** Copyright (c) 2001-2014
5 **
6 ** This file is part of the QuickFIX FIX Engine
7 **
8 ** This file may be distributed under the terms of the quickfixengine.org
9 ** license as defined by quickfixengine.org and appearing in the file
10 ** LICENSE included in the packaging of this file.
11 **
12 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 **
15 ** See http://www.quickfixengine.org/LICENSE for licensing information.
16 **
17 ** Contact ask@quickfixengine.org if any conditions of this licensing are
18 ** not clear to you.
19 **
20 ****************************************************************************/
21 
22 #ifndef FIX_FIELDMAP
23 #define FIX_FIELDMAP
24 
25 #ifdef _MSC_VER
26 #pragma warning( disable: 4786 )
27 #endif
28 
29 #include "Field.h"
30 #include "MessageSorters.h"
31 #include "Exceptions.h"
32 #include "Utility.h"
33 #include <map>
34 #include <vector>
35 #include <sstream>
36 #include <algorithm>
37 
38 namespace FIX
39 {
46 class FieldMap
47 {
48 
49  class sorter
50  {
51  public:
52  explicit sorter( const message_order& order ) : m_order( order ) {}
53 
54  bool operator()( int tag, const FieldBase& right ) const
55  {
56  return m_order( tag, right.getTag() );
57  }
58 
59  bool operator()( const FieldBase& left, int tag ) const
60  {
61  return m_order( left.getTag(), tag );
62  }
63 
64  bool operator()( const FieldBase& left, const FieldBase& right ) const
65  {
66  return m_order( left.getTag(), right.getTag() );
67  }
68 
69  private:
70  const message_order& m_order;
71  };
72 
73  class finder
74  {
75  public:
76  explicit finder( int tag ) : m_tag( tag ) {}
77 
78  bool operator()( const FieldBase& field ) const
79  {
80  return m_tag == field.getTag();
81  }
82 
83  private:
84  int m_tag;
85  };
86 
87  enum { DEFAULT_SIZE = 16 };
88 
89 protected:
90 
91  FieldMap( const message_order& order, int size );
92 
93 public:
94 
95  typedef std::vector < FieldBase, ALLOCATOR< FieldBase > > Fields;
96  typedef std::map < int, std::vector < FieldMap* >, std::less<int>,
97  ALLOCATOR<std::pair<const int, std::vector< FieldMap* > > > > Groups;
98 
99  typedef Fields::iterator iterator;
100  typedef Fields::const_iterator const_iterator;
101  typedef Groups::iterator g_iterator;
102  typedef Groups::const_iterator g_const_iterator;
103 
104  FieldMap( const message_order& order =
106 
107  FieldMap( const int order[] );
108 
109  FieldMap( const FieldMap& copy );
110 
111  virtual ~FieldMap();
112 
113  FieldMap& operator=( const FieldMap& rhs );
114 
116  void setField( const FieldBase& field, bool overwrite = true )
117  throw( RepeatedTag )
118  {
119  if( !overwrite )
120  {
121  addField( field );
122  }
123  else
124  {
125  Fields::iterator i = findTag( field.getTag() );
126  if( i == m_fields.end() )
127  {
128  addField( field );
129  }
130  else
131  {
132  i->setString( field.getString() );
133  }
134  }
135  }
136 
138  void setField( int tag, const std::string& value )
139  throw( RepeatedTag, NoTagValue )
140  {
141  FieldBase fieldBase( tag, value );
142  setField( fieldBase );
143  }
144 
146  bool getFieldIfSet( FieldBase& field ) const
147  {
148  Fields::const_iterator iter = findTag( field.getTag() );
149  if ( iter == m_fields.end() )
150  return false;
151  field = (*iter);
152  return true;
153  }
154 
156  FieldBase& getField( FieldBase& field )
157  const throw( FieldNotFound )
158  {
159  field = getFieldRef( field.getTag() );
160  return field;
161  }
162 
164  const std::string& getField( int tag )
165  const throw( FieldNotFound )
166  {
167  return getFieldRef( tag ).getString();
168  }
169 
171  const FieldBase& getFieldRef( int tag )
172  const throw( FieldNotFound )
173  {
174  Fields::const_iterator iter = findTag( tag );
175  if ( iter == m_fields.end() )
176  throw FieldNotFound( tag );
177  return (*iter);
178  }
179 
181  const FieldBase* const getFieldPtr( int tag )
182  const throw( FieldNotFound )
183  {
184  return &getFieldRef( tag );
185  }
186 
188  bool isSetField( const FieldBase& field ) const
189  { return isSetField( field.getTag() ); }
191  bool isSetField( int tag ) const
192  { return findTag( tag ) != m_fields.end(); }
193 
195  void removeField( int tag );
196 
198  void addGroup( int tag, const FieldMap& group, bool setCount = true );
199 
201  void addGroupPtr( int tag, FieldMap * group, bool setCount = true );
202 
204  void replaceGroup( int num, int tag, const FieldMap& group );
205 
207  FieldMap& getGroup( int num, int tag, FieldMap& group ) const
208  throw( FieldNotFound )
209  {
210  return group = getGroupRef( num, tag );
211  }
212 
214  FieldMap& getGroupRef( int num, int tag ) const
215  throw( FieldNotFound )
216  {
217  Groups::const_iterator i = m_groups.find( tag );
218  if( i == m_groups.end() ) throw FieldNotFound( tag );
219  if( num <= 0 ) throw FieldNotFound( tag );
220  if( i->second.size() < (unsigned)num ) throw FieldNotFound( tag );
221  return *( *(i->second.begin() + (num-1) ) );
222  }
223 
225  FieldMap* getGroupPtr( int num, int tag ) const
226  throw( FieldNotFound )
227  {
228  return &getGroupRef( num, tag );
229  }
230 
232  void removeGroup( int num, int tag );
234  void removeGroup( int tag );
235 
237  bool hasGroup( int tag ) const;
239  bool hasGroup( int num, int tag ) const;
241  size_t groupCount( int tag ) const;
242 
244  void clear();
246  bool isEmpty();
247 
248  size_t totalFields() const;
249 
250  std::string& calculateString( std::string& ) const;
251 
252  int calculateLength( int beginStringField = FIELD::BeginString,
253  int bodyLengthField = FIELD::BodyLength,
254  int checkSumField = FIELD::CheckSum ) const;
255 
256  int calculateTotal( int checkSumField = FIELD::CheckSum ) const;
257 
258  iterator begin() { return m_fields.begin(); }
259  iterator end() { return m_fields.end(); }
260  const_iterator begin() const { return m_fields.begin(); }
261  const_iterator end() const { return m_fields.end(); }
262  g_iterator g_begin() { return m_groups.begin(); }
263  g_iterator g_end() { return m_groups.end(); }
264  g_const_iterator g_begin() const { return m_groups.begin(); }
265  g_const_iterator g_end() const { return m_groups.end(); }
266 
267 protected:
268 
269  friend class Message;
270 
271  void addField( const FieldBase& field )
272  {
273  Fields::iterator iter = findPositionFor( field.getTag() );
274  if( iter == m_fields.end() )
275  {
276  m_fields.push_back( field );
277  }
278  else
279  {
280  m_fields.insert( iter, field );
281  }
282  }
283 
284  // used to find data length fields during message decoding
285  // message fields are not yet sorted so regular find*** functions might return wrong results
286  const FieldBase& reverse_find( int tag ) const
287  {
288  Fields::const_reverse_iterator iter = std::find_if( m_fields.rbegin(), m_fields.rend(), finder( tag ) );
289  if( iter == m_fields.rend() )
290  throw FieldNotFound( tag );
291 
292  return *iter;
293  }
294 
295  // append field to message without sorting
296  // only applicable during message decoding
297  void appendField( const FieldBase& field )
298  {
299  m_fields.push_back( field );
300  }
301 
302  // sort fields after message decoding
303  void sortFields()
304  {
305  std::sort( m_fields.begin(), m_fields.end(), sorter(m_order) );
306  }
307 
308 private:
309 
310  Fields::const_iterator findTag( int tag ) const
311  {
312  return lookup( m_fields.begin(), m_fields.end(), tag );
313  }
314 
315  Fields::iterator findTag( int tag )
316  {
317  return lookup( m_fields.begin(), m_fields.end(), tag );
318  }
319 
320  template <typename Iterator>
321  Iterator lookup(Iterator begin, Iterator end, int tag) const
322  {
323 #if defined(__SUNPRO_CC)
324  std::size_t numElements;
325  std::distance( begin, end, numElements );
326 #else
327  std::size_t numElements = std::distance( begin, end );
328 #endif
329  if( numElements < 16 )
330  return std::find_if( begin, end, finder( tag ) );
331 
332  Iterator iter = std::lower_bound( begin, end, tag, sorter( m_order ) );
333  if( iter != end &&
334  iter->getTag() == tag )
335  {
336  return iter;
337  }
338 
339  return end;
340  }
341 
342  Fields::iterator findPositionFor( int tag )
343  {
344  if( m_fields.empty() )
345  return m_fields.end();
346 
347  const FieldBase& last = m_fields.back();
348  if( m_order( last.getTag(), tag ) ||
349  last.getTag() == tag )
350  {
351  return m_fields.end();
352  }
353 
354  return std::upper_bound( m_fields.begin(), m_fields.end(), tag, sorter( m_order ) );
355  }
356 
360 };
362 }
363 
364 #define FIELD_SET( MAP, FIELD ) \
365 bool isSet( const FIELD& field ) const \
366 { return (MAP).isSetField(field); } \
367 void set( const FIELD& field ) \
368 { (MAP).setField(field); } \
369 FIELD& get( FIELD& field ) const \
370 { return (FIELD&)(MAP).getField(field); } \
371 bool getIfSet( FIELD& field ) const \
372 { return (MAP).getFieldIfSet(field); }
373 
374 #define FIELD_GET_PTR( MAP, FLD ) \
375 (const FIX::FLD*)MAP.getFieldPtr( FIX::FIELD::FLD )
376 #define FIELD_GET_REF( MAP, FLD ) \
377 (const FIX::FLD&)MAP.getFieldRef( FIX::FIELD::FLD )
378 #define FIELD_THROW_IF_NOT_FOUND( MAP, FLD ) \
379 if( !(MAP).isSetField( FIX::FIELD::FLD) ) \
380  throw FieldNotFound( FIX::FIELD::FLD )
381 #endif //FIX_FIELDMAP
382 
FIX::FieldMap::isSetField
bool isSetField(const FieldBase &field) const
Check to see if a field is set.
Definition: FieldMap.h:222
FIX::FieldMap::findTag
Fields::const_iterator findTag(int tag) const
Definition: FieldMap.h:344
FIX::FieldMap
Stores and organizes a collection of Fields.
Definition: FieldMap.h:63
Field.h
FIX::FieldMap::calculateTotal
int calculateTotal(int checkSumField=FIELD::CheckSum) const
Definition: FieldMap.cpp:275
FIX::FieldMap::hasGroup
bool hasGroup(int tag) const
Check to see any instance of a group exists.
Definition: FieldMap.cpp:185
FIX::FieldMap::clear
void clear()
Clear all fields from the map.
Definition: FieldMap.cpp:199
FIX::FieldMap::Groups
std::map< int, std::vector< FieldMap * >, std::less< int >, ALLOCATOR< std::pair< const int, std::vector< FieldMap * > > > > Groups
Definition: FieldMap.h:131
FIX::FieldMap::FieldMap
FieldMap(const message_order &order, int size)
Definition: FieldMap.cpp:51
FIX::FieldMap::groupCount
size_t groupCount(int tag) const
Count the number of instance of a group.
Definition: FieldMap.cpp:191
FIX::FieldMap::isEmpty
bool isEmpty()
Check if map contains any fields.
Definition: FieldMap.cpp:213
FIX::FieldMap::findPositionFor
Fields::iterator findPositionFor(int tag)
Definition: FieldMap.h:376
FIX::FieldMap::sorter::m_order
const message_order & m_order
Definition: FieldMap.h:121
FIX::FieldMap::g_end
g_iterator g_end()
Definition: FieldMap.h:297
FIX::FieldMap::addGroupPtr
void addGroupPtr(int tag, FieldMap *group, bool setCount=true)
Acquire ownership of Group object.
Definition: FieldMap.cpp:107
FIX::FieldMap::m_order
message_order m_order
Definition: FieldMap.h:393
FIX::FieldMap::m_groups
Groups m_groups
Definition: FieldMap.h:392
FIX::FieldMap::getFieldPtr
const FieldBase *const getFieldPtr(int tag) const
Get direct access to a field through a pointer.
Definition: FieldMap.h:215
FIX::FieldMap::~FieldMap
virtual ~FieldMap()
Definition: FieldMap.cpp:74
FIX::FieldMap::begin
iterator begin()
Definition: FieldMap.h:292
FIX::FieldMap::sorter
Definition: FieldMap.h:83
FIX::FieldMap::calculateString
std::string & calculateString(std::string &) const
Definition: FieldMap.cpp:232
FIX::FieldMap::addField
void addField(const FieldBase &field)
Definition: FieldMap.h:305
FIX::FieldMap::g_begin
g_iterator g_begin()
Definition: FieldMap.h:296
FIX::FieldMap::getGroup
FieldMap & getGroup(int num, int tag, FieldMap &group) const
Get a specific instance of a group.
Definition: FieldMap.h:241
FIX::FieldMap::finder::finder
finder(int tag)
Definition: FieldMap.h:110
FIX::FieldMap::getFieldIfSet
bool getFieldIfSet(FieldBase &field) const
Get a field if set.
Definition: FieldMap.h:180
FIX::FieldMap::lookup
Iterator lookup(Iterator begin, Iterator end, int tag) const
Definition: FieldMap.h:355
FIX::FieldMap::replaceGroup
void replaceGroup(int num, int tag, const FieldMap &group)
Replace a specific instance of a group.
Definition: FieldMap.cpp:119
FIX::FieldMap::totalFields
size_t totalFields() const
Definition: FieldMap.cpp:218
sort
void sort(I begin, I end, const Pred &pred)
Definition: pugixml.cpp:6153
FIX::FieldBase::getTag
int getTag() const
Get the fields integer tag.
Definition: Field.h:178
FIX::FieldMap::m_fields
Fields m_fields
Definition: FieldMap.h:391
FIX::FieldMap::DEFAULT_SIZE
@ DEFAULT_SIZE
Definition: FieldMap.h:121
FIX::FieldMap::sorter::operator()
bool operator()(int tag, const FieldBase &right) const
Definition: FieldMap.h:105
FIX::FieldMap::sorter::sorter
sorter(const message_order &order)
Definition: FieldMap.h:103
FIX::FieldMap::appendField
void appendField(const FieldBase &field)
Definition: FieldMap.h:331
FIX::FieldNotFound
Field not found inside a message.
Definition: Exceptions.h:74
FIX::FieldMap::g_const_iterator
Groups::const_iterator g_const_iterator
Definition: FieldMap.h:136
FIX::FieldMap::getField
FieldBase & getField(FieldBase &field) const
Get a field without type checking.
Definition: FieldMap.h:190
FIX::FieldMap::removeField
void removeField(int tag)
Remove a field. If field is not present, this is a no-op.
Definition: FieldMap.cpp:173
FIX::FieldMap::Fields
std::vector< FieldBase, ALLOCATOR< FieldBase > > Fields
Definition: FieldMap.h:129
FIX
Definition: Acceptor.cpp:34
FIX::FieldMap::getFieldRef
const FieldBase & getFieldRef(int tag) const
Get direct access to a field through a reference.
Definition: FieldMap.h:205
FIX::FieldMap::Message
friend class Message
Definition: FieldMap.h:303
FIX::FieldMap::addGroup
void addGroup(int tag, const FieldMap &group, bool setCount=true)
Add a group.
Definition: FieldMap.cpp:100
FIX::FieldMap::getGroupRef
FieldMap & getGroupRef(int num, int tag) const
Get direct access to a field through a reference.
Definition: FieldMap.h:248
FIX::FieldMap::setField
void setField(const FieldBase &field, bool overwrite=true)
Set a field without type checking.
Definition: FieldMap.h:150
FIX::FieldMap::finder::operator()
bool operator()(const FieldBase &field) const
Definition: FieldMap.h:112
FIX::FieldMap::g_iterator
Groups::iterator g_iterator
Definition: FieldMap.h:135
FIX::FieldMap::end
iterator end()
Definition: FieldMap.h:293
FIX::FieldBase
Base representation of all Field classes.
Definition: Field.h:66
MessageSorters.h
FIX::message_order::normal
@ normal
Definition: MessageSorters.h:133
FIX::FieldMap::reverse_find
const FieldBase & reverse_find(int tag) const
Definition: FieldMap.h:320
Exceptions.h
FIX::FieldMap::finder::m_tag
int m_tag
Definition: FieldMap.h:118
FIX::FieldMap::iterator
Fields::iterator iterator
Definition: FieldMap.h:133
FIX::FieldMap::getGroupPtr
FieldMap * getGroupPtr(int num, int tag) const
Get direct access to a field through a pointer.
Definition: FieldMap.h:259
FIX::FieldMap::removeGroup
void removeGroup(int num, int tag)
Remove a specific instance of a group.
Definition: FieldMap.cpp:128
FIX::message_order
Sorts fields in header, normal, or trailer order.
Definition: MessageSorters.h:130
FIX::FieldMap::sortFields
void sortFields()
Definition: FieldMap.h:337
FIX::FieldMap::calculateLength
int calculateLength(int beginStringField=FIELD::BeginString, int bodyLengthField=FIELD::BodyLength, int checkSumField=FIELD::CheckSum) const
Definition: FieldMap.cpp:250
FIX::NoTagValue
Field exists in message without a value.
Definition: Exceptions.h:145
Utility.h
FIX::FieldMap::operator=
FieldMap & operator=(const FieldMap &rhs)
Definition: FieldMap.cpp:79
FIX::FieldMap::finder
Definition: FieldMap.h:107
FIX::RepeatedTag
Repeated tag not part of repeating group.
Definition: Exceptions.h:216
FIX::FieldMap::const_iterator
Fields::const_iterator const_iterator
Definition: FieldMap.h:134
FIX::FieldBase::getString
const std::string & getString() const
Get the string representation of the fields value.
Definition: Field.h:186

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001