fix8  version 1.4.0
Open Source C++ FIX Framework
message.hpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------------------------------
2 /*
3 
4 Fix8 is released under the GNU LESSER GENERAL PUBLIC LICENSE Version 3.
5 
6 Fix8 Open Source FIX Engine.
7 Copyright (C) 2010-16 David L. Dight <fix@fix8.org>
8 
9 Fix8 is free software: you can redistribute it and / or modify it under the terms of the
10 GNU Lesser General Public License as published by the Free Software Foundation, either
11 version 3 of the License, or (at your option) any later version.
12 
13 Fix8 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
14 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 You should have received a copy of the GNU Lesser General Public License along with Fix8.
17 If not, see <http://www.gnu.org/licenses/>.
18 
19 BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO
20 THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
21 COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
22 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
24 THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
25 YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
26 
27 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
28 HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
29 ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
30 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
31 NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
32 THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
33 HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 
35 */
36 //-------------------------------------------------------------------------------------------------
37 #ifndef FIX8_MESSAGE_HPP_
38 #define FIX8_MESSAGE_HPP_
39 
40 #include <vector>
41 #if defined FIX8_PREENCODE_MSG_SUPPORT
42 #include <array>
43 #endif
44 
45 //-------------------------------------------------------------------------------------------------
46 namespace FIX8 {
47 
48 //-------------------------------------------------------------------------------------------------
49 class MessageBase;
50 class Message;
51 class Session;
52 class GroupBase;
53 using GroupElement = std::vector<MessageBase *>;
54 
55 //-------------------------------------------------------------------------------------------------
56 using Groups = std::map<unsigned short, GroupBase *>;
57 
59 class GroupBase
60 {
62  unsigned short _fnum;
65 
66 public:
69  GroupBase(const unsigned short fnum) : _fnum(fnum) {}
70 
72  virtual ~GroupBase() { clear(false); }
73 
77  virtual MessageBase *create_group(bool deepctor=true) const = 0;
78 
82  virtual GroupBase *create_nested_group(unsigned short fnum) const { return nullptr; }
83 
86  void add(MessageBase *what) { _msgs.push_back(what); }
87 
90  void operator+=(MessageBase *what) { add(what); }
91 
95  GroupBase& operator<<(MessageBase *what) { add(what); return *this; }
96 
99  size_t size() const { return _msgs.size(); }
100 
104  MessageBase *operator[](const unsigned idx) const { return get_element(idx); }
105 
109  MessageBase *get_element(const unsigned idx) const { return idx < _msgs.size() ? _msgs[idx] : nullptr; }
110 
113  void clear(bool reuse=true);
114 
119  friend std::ostream& operator<<(std::ostream& os, const GroupBase& what);
120 
121  friend class MessageBase;
122 };
123 
124 //-------------------------------------------------------------------------------------------------
126 class Router
127 {
128 public:
130  virtual ~Router() {}
131 
135  virtual bool operator()(const Message *msg) const { return false; }
136 
140  virtual bool operator()(const Message *msg) { return false; }
141 };
142 
144 class Minst
145 {
148  struct _gen
149  {
153  template<typename T>
154  static Message *_make(bool deepctor) { return new T(deepctor); }
155 
159  template<typename T, typename R>
160  static Message *_make(bool deepctor) { return reinterpret_cast<Message *>(new T(deepctor)); }
161 
162 #if defined FIX8_HAVE_EXTENDED_METADATA
163 
166  template<typename T, typename R = void>
167  static const TraitHelper& _make_traits()
168  {
169  static const TraitHelper _helper { T::get_traits(), T::get_fieldcnt() };
170  return _helper;
171  }
172 #endif
173  };
174 
175 public:
176  std::function<Message *(bool)> _do;
177 #if defined FIX8_HAVE_EXTENDED_METADATA
178  const TraitHelper& (&_get_traits)();
179 #endif
180 
183  template<typename T, typename... args>
184  Minst(Type2Type<T, args...>) : _do(_gen::_make<T, args...>)
185 #if defined FIX8_HAVE_EXTENDED_METADATA
186  , _get_traits(_gen::_make_traits<T, args...>)
187 #endif
188  {}
189 };
190 
193 {
194  const Minst _create;
195  const char *_name, *_comment;
196 };
197 
198 //-------------------------------------------------------------------------------------------------
200 //-------------------------------------------------------------------------------------------------
201 using c_str_compare = std::function<bool(const char *, const char *)>;
202 using msg_create = std::function<Message *(bool)>;
204 using ReverseMsgTable = std::map<const char * const, const BaseMsgEntry *, c_str_compare>;
206 using ReverseFieldTable = std::map<const char * const, const BaseEntry *, c_str_compare>;
207 
208 //-------------------------------------------------------------------------------------------------
211 {
213  const unsigned _version;
214 
216  const MsgTable& _bme;
218  const FieldTable& _be;
220  const char **_cn;
222  const unsigned _flu_sz;
224  const BaseEntry **_flu;
230  const size_t _preamble_sz;
231 
234  static bool _comp(const char *p1, const char *p2) { return ::strcmp(p1, p2) < 0; }
235 
242  F8MetaCntx(const unsigned version, const MsgTable& bme, const FieldTable& be, const char **cn, const f8String& bg)
243  : _version(version), _bme(bme), _be(be), _cn(cn),
244  _flu_sz(_be.at(_be.size() - 1)->_key + 1), _flu(new const BaseEntry *[_flu_sz]),
245  _mk_hdr(_bme.find_ref("header")._create._do), _mk_trl(_bme.find_ref("trailer")._create._do),
246  _beginStr(bg), _preamble_sz(2 + _beginStr.size() + 1 + 3),
247  _reverse_msgtable(_comp), _reverse_fieldtable(_comp)
248  {
249  if (_flu_sz == 1)
250  throw f8Exception("F8MetaCntx initialisation incomplete");
251  std::fill(_flu, _flu + _flu_sz, nullptr);
252  for (unsigned offset(0); offset < _be.size(); ++offset)
253  *(_flu + _be.at(offset)->_key) = &_be.at(offset)->_value;
254 
255  std::for_each(_be.begin(), _be.end(), [this](const FieldTable::Pair& pp)
256  { _reverse_fieldtable.emplace(std::make_pair(pp.second()._name, &pp.second())); });
257  std::for_each(_bme.begin(), _bme.end(), [this](const MsgTable::Pair& pp)
258  { _reverse_msgtable.emplace(std::make_pair(pp.second()._name, &pp.second())); });
259  }
260 
262  ~F8MetaCntx() { delete[] _flu; _flu = nullptr; }
263 
267  const BaseEntry *find_be(const unsigned short fnum) const
268  { return fnum < _flu_sz ? _flu[fnum] : nullptr; }
269 
273  const BaseEntry *reverse_find_be(const char *fieldstr) const
274  {
275  if (fieldstr && *fieldstr)
276  {
277  auto itr(_reverse_fieldtable.find(fieldstr));
278  return itr != _reverse_fieldtable.cend() ? itr->second : nullptr;
279  }
280  return nullptr;
281  }
282 
286  unsigned short reverse_find_fnum(const char *fieldstr) const
287  {
288  if (fieldstr && *fieldstr)
289  {
290  auto itr(_reverse_fieldtable.find(fieldstr));
291  return itr != _reverse_fieldtable.cend() ? itr->second->_fnum : 0;
292  }
293  return 0;
294  }
295 
300  BaseField *create_field(unsigned short fnum, const char *from) const
301  {
302  const BaseEntry *be(find_be(fnum));
303  return be ? be->_create._do(from, be->_rlm, -1) : nullptr;
304  }
305 
310  BaseField *create_field(const char *tag, const char *from) const
311  {
312  const BaseEntry *be(reverse_find_be(tag));
313  return be ? be->_create._do(from, be->_rlm, -1) : nullptr;
314  }
315 
319  const BaseMsgEntry *find_bme(const char *tag) const { return _bme.find_ptr(tag); }
320 
324  const BaseMsgEntry *reverse_find_bme(const char *msgstr) const
325  {
326  auto itr(_reverse_msgtable.find(msgstr));
327  return itr != _reverse_msgtable.cend() ? itr->second : nullptr;
328  }
329 
334  Message *create_msg_from_longname(const char *tag, bool deepctor=true) const
335  {
336  const BaseMsgEntry *bme(reverse_find_bme(tag));
337  return bme ? bme->_create._do(deepctor) : nullptr;
338  }
339 
344  Message *create_msg(const char *tag, bool deepctor=true) const
345  {
346  const BaseMsgEntry *bme(find_bme(tag));
347  return bme ? bme->_create._do(deepctor) : nullptr;
348  }
349 
352  unsigned version() const { return _version; }
353 
356  const f8String& get_beginStr() const { return _beginStr; }
357 
358 #if defined FIX8_HAVE_EXTENDED_METADATA
359  //----------------------------------------------------------------------------------------------
360  // The following methods can be used to iterate and interrogate static traits
361  //----------------------------------------------------------------------------------------------
362  using const_iterator = const FieldTrait*;
363  using const_internal_result = std::pair<const_iterator, const_iterator>;
364  static const_iterator find(unsigned short fnum, const TraitHelper& from)
365  {
366  const const_internal_result res(std::equal_range (from._traits, from._traits + from._fieldcnt,
367  FieldTrait(fnum), FieldTrait::Compare()));
368  return res.first != res.second ? res.first : nullptr;
369  }
370 
371  static const_iterator begin(const TraitHelper& from) { return from._traits; }
372  static const_iterator end(const TraitHelper& from) { return from._traits + from._fieldcnt; }
373 #endif
374 };
375 
376 //-------------------------------------------------------------------------------------------------
377 using Fields = std::map <unsigned short, BaseField *>;
378 using Positions = std::multimap<unsigned short, BaseField *>;
379 
382 {
385 
386 protected:
392  const F8MetaCntx& _ctx;
393 
399  static unsigned extract_header(const f8String& from, char *len, char *mtype);
400 
405  static unsigned extract_trailer(const f8String& from, f8String& chksum);
406 
407  // used by the printer
408  F8API static unsigned _tabsize;
409 
410 public:
418  template<typename InputIterator>
419  MessageBase(const struct F8MetaCntx& ctx, const f8String& msgType, const InputIterator begin, const size_t cnt,
420  const FieldTrait_Hash_Array *ftha) : _fp(begin, cnt, ftha),
421  _msgType(msgType), _ctx(ctx) {}
422 
424  F8API MessageBase(const MessageBase& from);
426  F8API MessageBase& operator=(const MessageBase& that);
427 
429  virtual ~MessageBase() { clear(false); }
430 
433  virtual void clear(bool reuse=true)
434  {
435  std::for_each(_fields.begin(), _fields.end(), [](Fields::value_type& pp) { delete pp.second; pp.second = nullptr; });
436  std::for_each(_groups.begin(), _groups.end(), [](Groups::value_type& pp) { delete pp.second; pp.second = nullptr; });
437  if (reuse)
438  {
439  _fields.clear();
440  //_groups.clear();
442  _pos.clear();
443  }
444  }
445 
447  void clear_positions() { _pos.clear(); }
448 
451  size_t size() const { return _fp.size(); }
452 
459  F8API unsigned decode(const f8String& from, unsigned offset, unsigned ignore=0, bool permissive_mode=false);
460 
468  unsigned decode_group(GroupBase *grpbase, const unsigned short fnum, const f8String& from,
469  unsigned s_offset, unsigned ignore);
470 
474  F8API size_t encode(std::ostream& to) const;
475 
479  F8API size_t encode(char *to) const;
480 
485  F8API size_t encode_group(const unsigned short fnum, std::ostream& to) const;
486 
491  F8API size_t encode_group(const unsigned short fnum, char *to) const;
492 
496  virtual GroupBase *create_nested_group(unsigned short fnum) const { return nullptr; }
497 
500  F8API unsigned check_positions();
501 
507  F8API unsigned copy_legal(MessageBase *to, bool force=false) const;
508 
515  F8API unsigned move_legal(MessageBase *to, bool force=false);
516 
518  void push_unknown(MessageBase *to) const
519  {
520  if (_unknown.size() && to)
521  to->_unknown = _unknown;
522  }
523 
526  void check_set_rlm(BaseField *where) const
527  {
528  if (!where->_rlm)
529  {
530  const BaseEntry *tbe(_ctx.find_be(where->_fnum));
531  if (tbe && tbe->_rlm)
532  where->_rlm = tbe->_rlm; // populate realm;
533  }
534  }
535 
538  const f8String& get_msgtype() const { return _msgType; }
539 
544  void add_field_decoder(const unsigned short fnum, const unsigned pos, BaseField *what)
545  {
546  _fields.insert({fnum, what});
547  _pos.insert({pos, what});
548  }
549 
556  void add_field(const unsigned short fnum, Presence::const_iterator itr, const unsigned pos, BaseField *what, bool check)
557  {
558  if (check && _fp.get(fnum, itr, FieldTrait::present)) // for now, silently replace duplicate
559  {
560  glout_debug << _msgType << " replacing field:" << fnum;
561  delete replace(fnum, itr, what);
562  return;
563  }
564 
565  _fields.insert({fnum, what});
566  _pos.insert({pos, what});
567  _fp.set(fnum, itr, FieldTrait::present);
568  }
569 
576  void add_field(const unsigned short fnum, Fields::iterator fitr, const unsigned pos, BaseField *what, bool check=true)
577  {
579  if (check && _fp.get(fnum, itr, FieldTrait::present)) // for now, silently replace duplicate
580  {
581  glout_debug << _msgType << " replacing field:" << fnum;
582  delete replace(fnum, itr, what);
583  return;
584  }
585 
586  _fields.insert(fitr, {fnum, what});
587  _pos.insert({pos, what});
588  _fp.set(fnum, itr, FieldTrait::present);
589  }
590 
596  void add_field(const unsigned short fnum, const unsigned pos, BaseField *what, bool check=true)
597  {
599  if (check && _fp.get(fnum, itr, FieldTrait::present)) // for now, silently replace duplicate
600  {
601  glout_debug << _msgType << " replacing field:" << fnum;
602  delete replace(fnum, itr, what);
603  return;
604  }
605 
606  _fields.insert({fnum, what});
607  _pos.insert({pos, what});
608  _fp.set(fnum, itr, FieldTrait::present);
609  }
610 
614  void set(const unsigned short field, FieldTrait::TraitTypes type=FieldTrait::present) { _fp.set(field, type); }
615 
620  template<typename T>
621  bool add_field(T *what)
622  {
624  if (_fp.has(T::get_field_id(), itr))
625  {
626  add_field(T::get_field_id(), itr, _fp.getPos(T::get_field_id(), itr), what, true);
627  return true;
628  }
629  throw InvalidField(T::get_field_id());
630  return false;
631  }
632 
637  bool add_field(BaseField *what)
638  {
639  const unsigned short& fnum(what->_fnum);
641  if (_fp.has(fnum, itr))
642  {
643  add_field(fnum, itr, _fp.getPos(fnum, itr), what, true);
644  return true;
645  }
646  throw InvalidField(fnum);
647  return false;
648  }
649 
650  Groups& get_groups() { return _groups; }
651 
656  template<typename T>
657  bool operator+=(T *what) { return add_field(what); }
658 
663  template<typename T>
664  MessageBase& operator<<(T *what) { add_field(what); return *this; }
665 
670  template<typename T>
671  bool get(T& to) const
672  {
673  Fields::const_iterator fitr(_fields.find(T::get_field_id()));
674  if (fitr == _fields.end())
675  return false;
676  to.set(fitr->second->from<T>().get());
677  if (fitr->second->_rlm)
678  to._rlm = fitr->second->_rlm;
679  return true;
680  }
681 
685  template<typename T>
686  bool has() const { return _fp.get(T::get_field_id()); }
687 
691  bool is_legal(unsigned short fnum) const { return _fp.has(fnum); }
692 
696  template<typename T>
697  bool is_legal() const { return _fp.has(T::get_field_id()); }
698 
702  template<typename T>
703  const T *get() const
704  {
705  Fields::const_iterator fitr(_fields.find(T::get_field_id()));
706  return fitr == _fields.cend() ? nullptr : &fitr->second->from<T>();
707  }
708 
713  template<typename T>
714  bool operator()(T& to) const { return get(to); }
715 
719  template<typename T>
720  const T *operator()() const { return get<T>(); }
721 
725  bool have(const unsigned short fnum) const { return _fp.get(fnum, FieldTrait::present); }
726 
730  Fields::const_iterator find_field(const unsigned short fnum) const { return _fields.find(fnum); }
731 
735  BaseField *get_field(const unsigned short fnum) const
736  {
737  auto itr(_fields.find(fnum));
738  return itr != _fields.cend() ? itr->second : nullptr;
739  }
740 
744  BaseField *get_field_by_name(const char *tag) const
745  {
746  auto itr(_fields.find(_ctx.reverse_find_fnum(tag)));
747  return itr != _fields.cend() ? itr->second : nullptr;
748  }
749 
752  Fields::const_iterator fields_begin() const { return _fields.begin(); }
753 
756  Fields::const_iterator fields_end() const { return _fields.end(); }
757 
763  F8API BaseField *replace(const unsigned short fnum, Presence::const_iterator itr, BaseField *with);
764 
769  F8API BaseField *replace(const unsigned short fnum, BaseField *with);
770 
775  F8API GroupBase *replace(const unsigned short fnum, GroupBase *with);
776 
781  F8API BaseField *remove(const unsigned short fnum, Presence::const_iterator itr);
782 
786  F8API BaseField *remove(const unsigned short fnum);
787 
791  template<typename T>
792  GroupBase *find_group() const { return find_group(T::_fnum); }
793 
797  GroupBase *find_group(const unsigned short fnum) const
798  {
799  auto gitr(_groups.find(fnum));
800  return gitr != _groups.cend() ? gitr->second : nullptr;
801  }
802 
807  template<typename T>
808  GroupBase *find_add_group(GroupBase *grpbase=nullptr) { return find_add_group(T::_fnum, grpbase); }
809 
814  GroupBase *find_add_group(const unsigned short fnum, GroupBase *grpbase=nullptr)
815  {
816  auto gitr(_groups.find(fnum));
817  if (gitr != _groups.end())
818  return gitr->second;
819  GroupBase *gb1(grpbase ? grpbase->create_nested_group(fnum) : create_nested_group(fnum));
820  add_group(gb1);
821  return gb1;
822  }
823 
827  template<typename T>
828  void append_group(T *what) { _groups.insert(_groups.end(), {T::_fnum, what}); }
829 
832  void add_group(GroupBase *what) { _groups.insert({what->_fnum, what}); }
833 
837  MessageBase& operator<<(GroupBase *what) { add_group(what); return *this; }
838 
841  void operator+=(GroupBase *what) { add_group(what); }
842 
846  unsigned short getPos(const unsigned short field) const { return _fp.getPos(field); }
847 
851  bool add_trait(const FieldTrait& what) { return _fp.add(what); }
852 
857  template<typename InputIterator>
858  void add_trait(const InputIterator begin, const size_t cnt) { _fp.add(begin, cnt); }
859 
863  F8API virtual void print(std::ostream& os, int depth=0) const;
864 
868  F8API virtual void print_field(const unsigned short fnum, std::ostream& os) const;
869 
874  F8API virtual void print_group(const unsigned short fnum, std::ostream& os, int depth=0) const;
875 
878  const FieldTraits& get_fp() const { return _fp; }
879 
886  static unsigned extract_element(const char *from, const unsigned sz, char *tag, char *val)
887  {
888  enum { get_tag, get_value } state(get_tag);
889 
890  for (unsigned ii(0); ii < sz; ++ii)
891  {
892  switch (state)
893  {
894  case get_tag:
895  if (!isdigit(from[ii]))
896  {
897  if (from[ii] != default_assignment_separator)
898  return *val = *tag = 0;
899  state = get_value;
900  }
901  else
902  *tag++ = from[ii];
903  break;
904  case get_value:
905  if (from[ii] == default_field_separator)
906  {
907  *val = *tag = 0;
908  return ++ii;
909  }
910  *val++ = from[ii];
911  break;
912  }
913  }
914  return *val = *tag = 0;
915  }
916 
924  static unsigned extract_element_fixed_width(const char *from, const unsigned sz, const unsigned val_sz, char *tag, char *val)
925  {
926  *val = *tag = 0;
927  for (unsigned ii(0); ii < sz; ++ii)
928  {
929  if(isdigit(from[ii]))
930  {
931  *tag++ = from[ii];
932  continue;
933  }
934 
935  if (from[ii++] != default_assignment_separator || sz < (ii + val_sz))
936  break;
937 
938  ::memcpy(val, &from[ii], val_sz);
939  val[val_sz] = 0;
940  return ii + val_sz + 1; // account for field separator
941  }
942  return *val = *tag = 0;
943  }
944 
951  static unsigned extract_element(const char *from, const unsigned sz, f8String& tag, f8String& val)
952  {
953  enum { get_tag, get_value } state(get_tag);
954  tag.clear();
955  val.clear();
956 
957  for (unsigned ii(0); ii < sz; ++ii)
958  {
959  switch (state)
960  {
961  case get_tag:
962  if (!isdigit(from[ii]))
963  {
964  if (from[ii] != default_assignment_separator)
965  return 0;
966  state = get_value;
967  }
968  else
969  tag += from[ii];
970  break;
971  case get_value:
972  if (from[ii] == default_field_separator)
973  return ++ii;
974  val += from[ii];
975  break;
976  }
977  }
978  return 0;
979  }
980 
985  friend std::ostream& operator<<(std::ostream& os, const MessageBase& what) { what.print(os); return os; }
986  friend class Message;
987 
990  static void set_tabsize (unsigned tabsize) { _tabsize = tabsize; }
991 
994  static unsigned get_tabsize () { return _tabsize; }
995 
999  static bool has_group_count(const BaseField *bf) { return static_cast<const Field<int, 0> *>(bf)->get() > 0; }
1000 
1003  void print_fp(std::ostream& os) { os << _fp; }
1004 
1007  virtual begin_string *get_begin_string() { return nullptr; }
1008 
1011  virtual body_length *get_body_length() { return nullptr; }
1012 
1015  virtual msg_type *get_msg_type() { return nullptr; }
1016 
1019  virtual check_sum *get_check_sum() { return nullptr; }
1020 
1023  const f8String& get_unknown() const { return _unknown; }
1024 };
1025 
1026 //-------------------------------------------------------------------------------------------------
1027 inline void GroupBase::clear(bool reuse)
1028 {
1029  std::for_each (_msgs.begin(), _msgs.end(), [](MessageBase *pp) { delete pp; });
1030  if (reuse)
1031  _msgs.clear();
1032 }
1033 
1034 //-------------------------------------------------------------------------------------------------
1035 #if defined FIX8_CODECTIMING
1036 struct codec_timings
1037 {
1038  double _cpu_used;
1039  unsigned _msg_count;
1040 
1041  codec_timings() : _cpu_used(), _msg_count() {}
1042 };
1043 
1044 #endif
1045 
1046 //-------------------------------------------------------------------------------------------------
1047 #if defined FIX8_SIZEOF_UNSIGNED_LONG && FIX8_SIZEOF_UNSIGNED_LONG == 8
1048 #ifndef _MSC_VER
1049 constexpr unsigned long COLLAPSE_INT64(unsigned long x)
1050  { return x + (x >> 8) + (x >> 16) + (x >> 24) + (x >> 32) + (x >> 40) + (x >> 48) + (x >> 56); }
1051 #else
1052 #define COLLAPSE_INT64(x) (x + (x >> 8) + (x >> 16) + (x >> 24) + (x >> 32) + (x >> 40) + (x >> 48) + (x >> 56))
1053 #endif
1054 #endif
1055 
1056 //-------------------------------------------------------------------------------------------------
1058 class Message : public MessageBase
1059 {
1060 #if defined FIX8_CODECTIMING
1061  static codec_timings _encode_timings, _decode_timings;
1062 #endif
1063 
1064 protected:
1066  unsigned _custom_seqnum;
1068 #if defined FIX8_RAW_MSG_SUPPORT
1069  mutable f8String _rawmsg;
1070  mutable int _begin_payload = -1;
1071  mutable unsigned _payload_len = 0;
1072 #endif
1073 #if defined FIX8_PREENCODE_MSG_SUPPORT
1074  mutable std::array<char, FIX8_MAX_MSG_LENGTH> _preencode;
1075  mutable size_t _preencode_len = 0;
1076 #endif
1077 
1078 public:
1086  template<typename InputIterator>
1087  Message(const F8MetaCntx& ctx, const f8String& msgType, const InputIterator begin, const size_t cnt,
1088  const FieldTrait_Hash_Array *ftha)
1089  : MessageBase(ctx, msgType, begin, cnt, ftha),_header(ctx._mk_hdr(true)),
1090  _trailer(ctx._mk_trl(true)), _custom_seqnum(), _no_increment(), _end_of_batch(true)
1091  {}
1092 
1094  virtual ~Message() { delete _header; delete _trailer; }
1095 
1098  MessageBase *Header() const { return _header; }
1099 
1102  MessageBase *Trailer() const { return _trailer; }
1103 
1106  MessageBase *Header() { return _header; }
1107 
1111 
1118  unsigned decode(const f8String& from, unsigned offset=0, unsigned ignore=0, bool permissive_mode=false)
1119  {
1120  const unsigned hlen(_header->decode(from, offset, 0, permissive_mode));
1121  const unsigned blen(MessageBase::decode(from, hlen, 0, permissive_mode));
1122 #if defined FIX8_RAW_MSG_SUPPORT
1123  _begin_payload = hlen;
1124  _payload_len = blen;
1125  _rawmsg = from;
1126 #endif
1127  return _trailer->decode(from, blen, ignore, permissive_mode);
1128  }
1129 
1133  F8API size_t encode(f8String& to) const;
1134 
1138  F8API size_t encode(char **to) const;
1139 
1142  F8API Message *clone() const;
1143 
1147  virtual bool process(Router& rt) const { return (rt)(this); }
1148 
1151  virtual bool is_admin() const { return false; }
1152 
1155  virtual void clear(bool reuse=true)
1156  {
1157  if (_header)
1158  _header->clear(reuse);
1159  if (_trailer)
1160  _trailer->clear(reuse);
1161  MessageBase::clear(reuse);
1162  }
1163 
1170  static unsigned calc_chksum(const char *from, const size_t sz, const unsigned offset=0, const int len=-1)
1171  {
1172 #if defined FIX8_SIZEOF_UNSIGNED_LONG && FIX8_SIZEOF_UNSIGNED_LONG == 8
1173  // steroid chksum algorithm by charles.cooper@lambda-tg.com
1174  // Basic strategy is to unroll the loop. normally adding in a loop
1175  // is slow because of the dependency, the cpu has to finish each loop
1176  // before it starts the next one and is unable to pipeline. one
1177  // way to get around this is to have multiple registers and have
1178  // multiple adds per loop, then consolidating at the end
1179  // as in unroll_checksum.
1180  // that is slow though because there is a lot of wasted space and
1181  // the cpu has to do a lot of adds.
1182  // key is that addition of a word is going to be faster
1183  // than addition of two chars, and also each word has 8 chars in it.
1184  // so we get 8 adds per loop. long1 + long2 is almost like
1185  // looping over two arrays of 8 chars and adding them element wise.
1186  // except for the overflow. so we have to keep track of the overflow
1187  // and get rid of it at the end.
1188 
1189  const unsigned long OVERFLOW_MASK (1UL << 8 | 1UL << 16 | 1UL << 24 | 1UL << 32 | 1UL << 40 | 1UL << 48 | 1UL << 56);
1190  unsigned long ret{}, overflow{};
1191  from += offset;
1192  const unsigned long elen (len != -1 ? len : sz);
1193  size_t ii{};
1194  for (; ii < (elen - elen % 8); ii += 8)
1195  {
1196  unsigned long expected_overflow((ret & OVERFLOW_MASK) ^ (OVERFLOW_MASK & *reinterpret_cast<const unsigned long*>(from + ii)));
1197  ret += *reinterpret_cast<const unsigned long*>(from + ii);
1198  overflow += (expected_overflow ^ ret) & OVERFLOW_MASK;
1199  }
1200  ret = COLLAPSE_INT64(ret);
1201  overflow = COLLAPSE_INT64(overflow);
1202  for (; ii < elen; ret += from[ii++]); // add up rest one by one
1203  return (ret - overflow) & 0xff;
1204 #else
1205  // native chksum algorithm
1206  unsigned val(0);
1207  const char *eptr(from + (len != -1 ? len + offset : sz - offset));
1208  for (const char *ptr(from + offset); ptr < eptr; val += *ptr++);
1209  return val % 256;
1210 #endif
1211  }
1212 
1218  static unsigned calc_chksum(const f8String& from, const unsigned offset=0, const int len=-1)
1219  { return calc_chksum(from.c_str(), from.size(), offset, len); }
1220 
1224  static f8String fmt_chksum(const unsigned val)
1225  {
1226  char buf[4] { '0', '0', '0', 0 };
1227  itoa<unsigned>(val, buf + (val > 99 ? 0 : val > 9 ? 1 : 2), 10);
1228  return f8String(buf);
1229  }
1230 
1238  static Message *factory(const F8MetaCntx& ctx, const char *from, bool no_chksum=false, bool permissive_mode=false)
1239  {
1240  const f8String to(from);
1241  return factory(ctx, to, no_chksum, permissive_mode);
1242  }
1243 
1251  F8API static Message *factory(const F8MetaCntx& ctx, const f8String& from, bool no_chksum=false, bool permissive_mode=false);
1252 
1255  virtual void set_custom_seqnum(unsigned seqnum) { _custom_seqnum = seqnum; }
1256 
1259  unsigned get_custom_seqnum() const { return _custom_seqnum; }
1260 
1263  virtual void set_no_increment(bool flag=true) { _no_increment = flag; }
1264 
1267  virtual bool get_no_increment() const { return _no_increment; }
1268 
1271  bool get_end_of_batch() const { return _end_of_batch; }
1272 
1275  void set_end_of_batch(bool is_end_of_batch) { _end_of_batch = is_end_of_batch; }
1276 
1280  {
1281  if (_header)
1282  {
1285  delete _header->remove(Common_MsgSeqNum);
1286  }
1287  if (_trailer)
1289  }
1290 
1292  void push_unknown(Message *to) const
1293  {
1294  if (_header)
1295  _header->push_unknown(to->_header);
1297  if (_trailer)
1298  _trailer->push_unknown(to->_trailer);
1299  }
1300 
1304  BaseField *get_field_flattened(const unsigned short fnum) const
1305  {
1306  auto itr (_fields.find(fnum));
1307  return itr != _fields.end() ? itr->second
1308  : (itr = _header->_fields.find(fnum)) != _header->_fields.end() ? itr->second
1309  : (itr = _trailer->_fields.find(fnum)) != _trailer->_fields.end() ? itr->second : nullptr;
1310  }
1311 
1315  BaseField *get_field_by_name_flattened(const char *tag) const
1316  {
1318  }
1319 
1320 #if defined FIX8_RAW_MSG_SUPPORT
1321 
1323  const f8String& get_rawmsg() const { return _rawmsg; }
1324 
1327  f8String::const_iterator begin_payload() const { return f8String::const_iterator(_rawmsg.data() + _begin_payload); }
1328 
1331  f8String::const_iterator end_payload() const { return f8String::const_iterator(_rawmsg.data() + _begin_payload + _payload_len); }
1332 
1335  unsigned get_payload_len() const { return _payload_len; }
1336 
1339  unsigned get_payload_begin() const { return _begin_payload; }
1340 #endif
1341 #if defined FIX8_PREENCODE_MSG_SUPPORT
1342 
1344  const char *get_preencode_msg() const { return _preencode_len ? _preencode.data() : nullptr; }
1345 
1348  size_t get_preencode_len() const { return _preencode_len; }
1349 
1352  size_t preencode() { return _preencode_len = MessageBase::encode(_preencode.data()); }
1353 #endif
1354 
1358  F8API virtual void print(std::ostream& os, int depth=0) const;
1359 
1364  friend std::ostream& operator<<(std::ostream& os, const Message& what) { what.print(os); return os; }
1365 
1366 #if defined FIX8_CODECTIMING
1367  F8API static void format_codec_timings(const f8String& md, std::ostream& ostr, codec_timings& tobj);
1368  F8API static void report_codec_timings(const f8String& tag);
1369 #endif
1370 };
1371 
1372 //-------------------------------------------------------------------------------------------------
1373 inline std::ostream& operator<<(std::ostream& os, const GroupBase& what)
1374 {
1375  for (const auto *pp : what._msgs)
1376  pp->print(os);
1377  return os;
1378 }
1379 
1380 } // FIX8
1381 
1382 #endif // FIX8_MESSAGE_HPP_
F8API unsigned move_legal(MessageBase *to, bool force=false)
Definition: message.cpp:315
const MsgTable & _bme
Framework generated lookup table to generate Fix messages.
Definition: message.hpp:216
const RealmBase * _rlm
Definition: field.hpp:132
bool have(const unsigned short fnum) const
Definition: message.hpp:725
unsigned tabsize(3)
const unsigned _flu_sz
Number of elements in Hash array.
Definition: message.hpp:222
void add_trait(const InputIterator begin, const size_t cnt)
Definition: message.hpp:858
FieldTraits _fp
Definition: message.hpp:388
Message * create_msg_from_longname(const char *tag, bool deepctor=true) const
Definition: message.hpp:334
F8API unsigned decode(const f8String &from, unsigned offset, unsigned ignore=0, bool permissive_mode=false)
Definition: message.cpp:87
MessageBase & operator<<(GroupBase *what)
Definition: message.hpp:837
void add(MessageBase *what)
Definition: message.hpp:86
const unsigned short Common_CheckSum(10)
BaseField *(&) _do(const char *from, const RealmBase *db, const int)
Definition: field.hpp:2069
static unsigned extract_trailer(const f8String &from, f8String &chksum)
Definition: message.cpp:80
void operator+=(GroupBase *what)
Definition: message.hpp:841
Binary comparitor functor.
Definition: traits.hpp:161
size_t size() const
Definition: message.hpp:99
virtual void clear(bool reuse=true)
Definition: message.hpp:1155
void push_unknown(MessageBase *to) const
Definition: message.hpp:518
const BaseMsgEntry * reverse_find_bme(const char *msgstr) const
Definition: message.hpp:324
Groups & get_groups()
Definition: message.hpp:650
virtual body_length * get_body_length()
Definition: message.hpp:1011
F8API MessageBase & operator=(const MessageBase &that)
Assignment operator.
BaseField * get_field_flattened(const unsigned short fnum) const
Definition: message.hpp:1304
F8API BaseField * remove(const unsigned short fnum, Presence::const_iterator itr)
Definition: message.cpp:646
const_iterator begin() const
Definition: f8types.hpp:133
virtual F8API void print_field(const unsigned short fnum, std::ostream &os) const
Definition: message.cpp:554
Base class for inbound message routing.
Definition: message.hpp:126
Message instantiation table entry.
Definition: message.hpp:192
const unsigned _version
4 digit fix version eg. 4.2r10 is 4210
Definition: message.hpp:213
Pair abstraction for use with GeneratedTable.
Definition: f8types.hpp:69
unsigned decode(const f8String &from, unsigned offset=0, unsigned ignore=0, bool permissive_mode=false)
Definition: message.hpp:1118
GroupBase * find_group() const
Definition: message.hpp:792
unsigned short getPos(const unsigned short field, Presence::const_iterator &itr) const
Definition: traits.hpp:639
Message * create_msg(const char *tag, bool deepctor=true) const
Definition: message.hpp:344
virtual bool operator()(const Message *msg)
Definition: message.hpp:140
virtual F8API void print(std::ostream &os, int depth=0) const
Definition: message.cpp:680
void add_field_decoder(const unsigned short fnum, const unsigned pos, BaseField *what)
Definition: message.hpp:544
Val _value
Definition: f8types.hpp:72
friend std::ostream & operator<<(std::ostream &os, const MessageBase &what)
Definition: message.hpp:985
static Message * _make(bool deepctor)
Definition: message.hpp:160
bool has(const unsigned short field, Presence::const_iterator &itr) const
Definition: traits.hpp:457
MessageBase * Header()
Definition: message.hpp:1106
static f8String fmt_chksum(const unsigned val)
Definition: message.hpp:1224
F8API size_t encode(f8String &to) const
Definition: message.cpp:500
static unsigned calc_chksum(const char *from, const size_t sz, const unsigned offset=0, const int len=-1)
Definition: message.hpp:1170
virtual void set_custom_seqnum(unsigned seqnum)
Definition: message.hpp:1255
F8API unsigned copy_legal(MessageBase *to, bool force=false) const
Definition: message.cpp:275
static Message * _make(bool deepctor)
Definition: message.hpp:154
unsigned decode_group(GroupBase *grpbase, const unsigned short fnum, const f8String &from, unsigned s_offset, unsigned ignore)
Definition: message.cpp:166
std::vector< MessageBase * > GroupElement
Definition: message.hpp:53
std::function< Message *(bool)> _do
Definition: message.hpp:176
const F8MetaCntx & _ctx
Definition: message.hpp:392
BaseField * get_field_by_name(const char *tag) const
Definition: message.hpp:744
BaseField * create_field(unsigned short fnum, const char *from) const
Definition: message.hpp:300
virtual begin_string * get_begin_string()
Definition: message.hpp:1007
virtual bool is_admin() const
Definition: message.hpp:1151
const Presence & get_presence() const
Definition: traits.hpp:658
ReverseMsgTable _reverse_msgtable
Definition: message.hpp:232
virtual bool operator()(const Message *msg) const
Definition: message.hpp:135
std::ostream & operator<<(std::ostream &os, const GroupBase &what)
Definition: message.hpp:1373
~F8MetaCntx()
Dtor.
Definition: message.hpp:262
std::function< bool(const char *, const char *)> c_str_compare
Field and Message metadata structures.
Definition: message.hpp:201
virtual ~GroupBase()
dtor
Definition: message.hpp:72
void push_unknown(Message *to) const
Definition: message.hpp:1292
virtual GroupBase * create_nested_group(unsigned short fnum) const
Definition: message.hpp:82
F8API unsigned check_positions()
Definition: message.cpp:218
const f8String _beginStr
Fix header beginstring.
Definition: message.hpp:228
virtual F8API void print_group(const unsigned short fnum, std::ostream &os, int depth=0) const
Definition: message.cpp:536
virtual check_sum * get_check_sum()
Definition: message.hpp:1019
#define glout_debug
Definition: logger.hpp:614
const char * _name
Definition: message.hpp:195
static bool _comp(const char *p1, const char *p2)
Definition: message.hpp:234
Abstract base class for all repeating groups.
Definition: message.hpp:59
MessageBase(const struct F8MetaCntx &ctx, const f8String &msgType, const InputIterator begin, const size_t cnt, const FieldTrait_Hash_Array *ftha)
Definition: message.hpp:419
bool operator()(T &to) const
Definition: message.hpp:714
TraitTypes
Trait bits.
Definition: traits.hpp:78
size_t size() const
Definition: f8types.hpp:176
virtual ~MessageBase()
Dtor.
Definition: message.hpp:429
static unsigned extract_header(const f8String &from, char *len, char *mtype)
Definition: message.cpp:51
Positions _pos
Definition: message.hpp:389
virtual MessageBase * create_group(bool deepctor=true) const =0
Used for static trait interrogation.
Definition: traits.hpp:57
const BaseEntry * reverse_find_be(const char *fieldstr) const
Definition: message.hpp:273
static bool has_group_count(const BaseField *bf)
Definition: message.hpp:999
Fields::const_iterator find_field(const unsigned short fnum) const
Definition: message.hpp:730
void add_field(const unsigned short fnum, Fields::iterator fitr, const unsigned pos, BaseField *what, bool check=true)
Definition: message.hpp:576
const F8MetaCntx & ctx()
Compiler generated metadata object, accessed through this function.
MessageBase * Trailer() const
Definition: message.hpp:1102
Base exception class.
Definition: f8exception.hpp:49
const f8String & get_msgtype() const
Definition: message.hpp:538
void set(const unsigned short field, FieldTrait::TraitTypes type=FieldTrait::present)
Definition: message.hpp:614
bool has() const
Definition: message.hpp:686
#define F8API
Definition: f8dll.h:60
void clear_flag(FieldTrait::TraitTypes type=FieldTrait::present)
Definition: traits.hpp:585
const size_t _preamble_sz
Preamble length.
Definition: message.hpp:230
const f8String & get_beginStr() const
Definition: message.hpp:356
std::map< unsigned short, GroupBase * > Groups
Definition: message.hpp:56
MessageBase * _trailer
Definition: message.hpp:1065
MessageBase * Header() const
Definition: message.hpp:1098
virtual ~Message()
Dtor.
Definition: message.hpp:1094
F8API Message * clone() const
Definition: message.cpp:668
ReverseFieldTable _reverse_fieldtable
Definition: message.hpp:233
bool get_end_of_batch() const
Definition: message.hpp:1271
msg_create _mk_trl
Definition: message.hpp:226
Type2Type idiom. Variadic template version. Kudos to Andrei Alexandrescu.
Definition: f8types.hpp:378
const RealmBase * _rlm
Definition: field.hpp:2080
unsigned short _fnum
field number
Definition: message.hpp:62
void clear_positions()
empty the positions map
Definition: message.hpp:447
static unsigned extract_element(const char *from, const unsigned sz, f8String &tag, f8String &val)
Definition: message.hpp:951
static unsigned extract_element(const char *from, const unsigned sz, char *tag, char *val)
Definition: message.hpp:886
BaseField * get_field(const unsigned short fnum) const
Definition: message.hpp:735
virtual GroupBase * create_nested_group(unsigned short fnum) const
Definition: message.hpp:496
const T * operator()() const
Definition: message.hpp:720
void clear(bool reuse=true)
Definition: message.hpp:1027
GroupBase * find_add_group(const unsigned short fnum, GroupBase *grpbase=nullptr)
Definition: message.hpp:814
F8API BaseField * replace(const unsigned short fnum, Presence::const_iterator itr, BaseField *with)
Definition: message.cpp:599
virtual bool process(Router &rt) const
Definition: message.hpp:1147
F8API size_t encode_group(const unsigned short fnum, std::ostream &to) const
Definition: message.cpp:409
unsigned _custom_seqnum
Definition: message.hpp:1066
MessageBase * get_element(const unsigned idx) const
Definition: message.hpp:109
const FieldTable & _be
Framework generated lookup table to generate Fix fields.
Definition: message.hpp:218
Structures for framework generated message creation and static trait interrogation.
Definition: message.hpp:144
Minst(Type2Type< T, args...>)
Definition: message.hpp:184
virtual void clear(bool reuse=true)
Definition: message.hpp:433
const unsigned short Common_MsgSeqNum(34)
const unsigned char default_assignment_separator('=')
default FIX assignment separator (=)
BaseField * create_field(const char *tag, const char *from) const
Definition: message.hpp:310
const unsigned short Common_BodyLength(9)
void set_end_of_batch(bool is_end_of_batch)
Definition: message.hpp:1275
void add_field(const unsigned short fnum, const unsigned pos, BaseField *what, bool check=true)
Definition: message.hpp:596
A complete Fix message with header, body and trailer.
Definition: message.hpp:1058
static Message * factory(const F8MetaCntx &ctx, const char *from, bool no_chksum=false, bool permissive_mode=false)
Definition: message.hpp:1238
bool get(const unsigned short field, FieldTrait::TraitTypes type=FieldTrait::present) const
Definition: traits.hpp:490
std::multimap< unsigned short, BaseField * > Positions
Definition: message.hpp:378
const char ** _cn
Framework generated component name table.
Definition: message.hpp:220
T get_value(const std::string &source)
Definition: f8utils.hpp:564
virtual bool get_no_increment() const
Definition: message.hpp:1267
Fields::const_iterator fields_end() const
Definition: message.hpp:756
size_t size() const
Definition: traits.hpp:484
static unsigned calc_chksum(const f8String &from, const unsigned offset=0, const int len=-1)
Definition: message.hpp:1218
MessageBase & operator<<(T *what)
Definition: message.hpp:664
static void set_tabsize(unsigned tabsize)
Definition: message.hpp:990
BaseField * get_field_by_name_flattened(const char *tag) const
Definition: message.hpp:1315
Field template. There will ONLY be partial template specialisations of this template.
Definition: field.hpp:256
virtual msg_type * get_msg_type()
Definition: message.hpp:1015
void operator+=(MessageBase *what)
Definition: message.hpp:90
const Inst _create
Definition: field.hpp:2077
void check_set_rlm(BaseField *where) const
Definition: message.hpp:526
GroupBase(const unsigned short fnum)
Definition: message.hpp:69
An invalid field was requested or added.
GroupBase * find_group(const unsigned short fnum) const
Definition: message.hpp:797
const f8String & get_unknown() const
Definition: message.hpp:1023
const unsigned short _fnum
Definition: field.hpp:129
unsigned version() const
Definition: message.hpp:352
GroupBase * find_add_group(GroupBase *grpbase=nullptr)
Definition: message.hpp:808
const BaseEntry * find_be(const unsigned short fnum) const
Definition: message.hpp:267
std::map< const char *const, const BaseMsgEntry *, c_str_compare > ReverseMsgTable
Definition: message.hpp:204
bool operator+=(T *what)
Definition: message.hpp:657
const unsigned char default_field_separator(0x1)
default FIX field separator (^A)
const unsigned short Common_BeginString(8)
bool add_field(T *what)
Definition: message.hpp:621
const FieldTraits & get_fp() const
Definition: message.hpp:878
unsigned get_custom_seqnum() const
Definition: message.hpp:1259
const char * _comment
Definition: message.hpp:195
msg_create _mk_hdr
References to the header and trailer create functions.
Definition: message.hpp:226
void add_field(const unsigned short fnum, Presence::const_iterator itr, const unsigned pos, BaseField *what, bool check)
Definition: message.hpp:556
void setup_reuse()
Definition: message.hpp:1279
void print_fp(std::ostream &os)
Definition: message.hpp:1003
The base field class (ABC) for all fields.
Definition: field.hpp:127
bool add(const FieldTrait &what)
Definition: traits.hpp:575
friend std::ostream & operator<<(std::ostream &os, const Message &what)
Definition: message.hpp:1364
static F8API unsigned _tabsize
Definition: message.hpp:408
A collection of FieldTraits for a message. Which fields are required, which are present.
Definition: traits.hpp:437
GroupBase & operator<<(MessageBase *what)
Definition: message.hpp:95
const BaseMsgEntry * find_bme(const char *tag) const
Definition: message.hpp:319
void add_group(GroupBase *what)
Definition: message.hpp:832
bool is_legal() const
Definition: message.hpp:697
virtual F8API void print(std::ostream &os, int depth=0) const
Definition: message.cpp:509
F8API size_t encode(std::ostream &to) const
Definition: message.cpp:373
const_iterator at(const size_t idx) const
Definition: f8types.hpp:172
const f8String & _msgType
Definition: message.hpp:391
std::map< unsigned short, BaseField * > Fields
Definition: message.hpp:377
std::function< Message *(bool)> msg_create
Definition: message.hpp:202
bool _no_increment
Definition: message.hpp:1067
size_t size() const
Definition: message.hpp:451
unsigned short reverse_find_fnum(const char *fieldstr) const
Definition: message.hpp:286
static unsigned get_tabsize()
Definition: message.hpp:994
bool is_legal(unsigned short fnum) const
Definition: message.hpp:691
GroupElement _msgs
vector of repeating messagebase groups
Definition: message.hpp:64
const BaseEntry ** _flu
Hash array for field lookup (built by ctor)
Definition: message.hpp:224
Message(const F8MetaCntx &ctx, const f8String &msgType, const InputIterator begin, const size_t cnt, const FieldTrait_Hash_Array *ftha)
Definition: message.hpp:1087
bool _end_of_batch
Definition: message.hpp:1067
Base class for all fix messages.
Definition: message.hpp:381
unsigned short getPos(const unsigned short field) const
Definition: message.hpp:846
MessageBase * _header
Definition: message.hpp:1065
const Minst _create
Definition: message.hpp:194
const Val * find_ptr(const Key &key) const
Definition: f8types.hpp:154
Static metadata context class - one per FIX xml schema.
Definition: message.hpp:210
f8String _unknown
pass through for permissive mode
Definition: message.hpp:384
Fields::const_iterator fields_begin() const
Definition: message.hpp:752
Fast map for statically generated data types. Assumes table is sorted. Complexity is O(logN)...
Definition: f8types.hpp:100
std::string f8String
Definition: f8types.hpp:47
virtual ~Router()
Dtor.
Definition: message.hpp:130
const_iterator end() const
Definition: f8types.hpp:137
bool add_field(BaseField *what)
Definition: message.hpp:637
void set(const unsigned short field, Presence::const_iterator &itr, FieldTrait::TraitTypes type)
Definition: traits.hpp:524
static unsigned extract_element_fixed_width(const char *from, const unsigned sz, const unsigned val_sz, char *tag, char *val)
Definition: message.hpp:924
virtual void set_no_increment(bool flag=true)
Definition: message.hpp:1263
std::map< const char *const, const BaseEntry *, c_str_compare > ReverseFieldTable
Definition: message.hpp:206
bool add_trait(const FieldTrait &what)
Definition: message.hpp:851
F8MetaCntx(const unsigned version, const MsgTable &bme, const FieldTable &be, const char **cn, const f8String &bg)
Definition: message.hpp:242
MessageBase * Trailer()
Definition: message.hpp:1110
void append_group(T *what)
Definition: message.hpp:828
Fast index lookup for FieldTrait.
Definition: traits.hpp:198
MessageBase * operator[](const unsigned idx) const
Definition: message.hpp:104