45 #if defined FIX8_CODECTIMING
46 codec_timings Message::_encode_timings, Message::_decode_timings;
53 const char *dptr(from.data());
54 const unsigned flen(static_cast<unsigned>(from.size()));
56 unsigned s_offset(0), result;
58 if ((result = extract_element(dptr, flen, tag, val)))
63 if ((result = extract_element(dptr + s_offset, flen - s_offset, tag, len)))
68 if ((result = extract_element(dptr + s_offset, flen - s_offset, tag, mtype)))
70 if (*tag !=
'3' || *(tag + 1) !=
'5')
83 return extract_element(from.data() + from.size() - 7, 6, tag, chksum);
89 const unsigned fsize(static_cast<unsigned>(from.size()) - ignore), npos(0xffffffff);
90 unsigned pos(static_cast<unsigned>(_pos.size())), last_valid_pos(npos);
91 const char *dptr(from.data());
93 size_t last_valid_offset(0);
95 for (
unsigned result; s_offset <= fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));)
97 unsigned short tv(fast_atoi<unsigned short>(tag));
99 if (itr == _fp.get_presence().end())
104 if (last_valid_pos == npos)
106 last_valid_pos = pos;
107 last_valid_offset = s_offset;
109 _unknown.append(dptr + s_offset, result);
121 else for(
unsigned ii(0); ii < 2; ++ii)
126 BaseField *bf(be->_create._do(val, be->_rlm, -1));
127 add_field_decoder(tv, ++pos, bf);
131 s_offset = decode_group(
nullptr, tv, from, s_offset, ignore);
136 const unsigned val_sz(fast_atoi<unsigned>(val));
139 result = extract_element_fixed_width(dptr + s_offset, fsize - s_offset, val_sz, tag, val);
143 const unsigned short lasttv(tv);
144 tv = fast_atoi<unsigned short>(tag);
145 if ((itr = _fp.get_presence().find(tv)) == _fp.get_presence().end())
153 const unsigned short missing(_fp.find_missing());
156 const BaseEntry *tbe(_ctx.find_be(missing));
158 ostr << tbe->
_name <<
" (" << missing <<
')';
162 return permissive_mode && last_valid_pos == pos ?
static_cast<unsigned>(last_valid_offset) : s_offset;
167 unsigned s_offset,
unsigned ignore)
170 if (!(grpbase = find_add_group(fnum, grpbase)))
172 const unsigned fsize(static_cast<unsigned>(from.size()) - ignore);
173 const char *dptr(from.data());
176 for (
bool ok(
true); ok && s_offset < fsize; )
178 unique_ptr<MessageBase> grp(grpbase->
create_group(
false));
180 for (
unsigned pos(0); s_offset < fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));)
182 const unsigned tv(fast_atoi<unsigned>(tag));
186 if (pos == 0 && grp->_fp.getPos(tv, itr) != 1)
189 if (!be || !grp->_fp.has(tv, itr))
195 BaseField *bf(be->_create._do(val, be->_rlm, -1));
196 grp->add_field(tv, itr, ++pos, bf,
false);
199 if (grp->_fp.is_group(tv, itr) && has_group_count(bf))
200 s_offset = grp->decode_group(grpbase, tv, from, s_offset, ignore);
203 const unsigned short missing(grp->_fp.find_missing());
206 const BaseEntry *tbe(_ctx.find_be(missing));
208 ostr << tbe->
_name <<
" (" << missing <<
')';
211 *grpbase << grp.release();
227 const unsigned hlen(extract_header(from, len, mtype));
235 const unsigned mlen(fast_atoi<unsigned>(len));
239 Message *msg(bme->_create._do(
false));
240 #if defined FIX8_CODECTIMING
243 msg->decode(from, hlen, 7, permissive_mode);
244 #if defined FIX8_CODECTIMING
246 ++_decode_timings._msg_count;
249 msg->_header->get_body_length()->set(mlen);
250 msg->_header->get_msg_type()->set(mtype);
251 #if defined FIX8_POPULATE_METADATA
252 msg->check_set_rlm(fitr->second);
255 const char *pp(from.data() + from.size() - 7);
256 if (*pp !=
'1' || *(pp + 1) !=
'0')
261 msg->_trailer->get_check_sum()->set(chksum);
262 const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, static_cast<unsigned>(from.size()) - 7));
263 if (chkval != mchkval)
278 for (
const auto& pp : _fp.get_presence())
286 for (
const auto *qq : gb->
_msgs)
294 BaseField *nf(get_field(pp._fnum)->copy());
295 #if defined FIX8_POPULATE_METADATA
300 delete to->
replace(pp._fnum, fpitr, nf);
318 for (
const auto& pp : _fp.get_presence())
324 auto gitr(_groups.find(pp._fnum));
327 delete to->
replace(pp._fnum, gitr->second);
330 gitr->second =
nullptr;
333 auto itr(_fields.find(pp._fnum));
336 delete to->
replace(pp._fnum, fpitr, itr->second);
339 itr->second =
nullptr;
351 const char *where(to);
352 for (
const auto& pp : _pos)
354 #if defined FIX8_POPULATE_METADATA
355 check_set_rlm(pp.second);
360 to += pp.second->encode(to);
362 to += encode_group(pp.second->_fnum, to);
367 to += _unknown.copy(to, _unknown.size());
375 const std::ios::pos_type where(to.tellp());
376 for (
const auto& pp : _pos)
378 #if defined FIX8_POPULATE_METADATA
379 check_set_rlm(pp.second);
384 pp.second->encode(to);
386 encode_group(pp.second->_fnum, to);
393 return to.tellp() - where;
399 const char *where(to);
403 for (
const auto *pp : grpbase->
_msgs)
404 to += pp->encode(to);
411 const std::ios::pos_type where(to.tellp());
415 for (
const auto *pp : grpbase->_msgs)
417 return to.tellp() - where;
426 #if defined FIX8_CODECTIMING
432 _header->get_msg_type()->set(_msgType);
434 #if defined FIX8_RAW_MSG_SUPPORT
435 msg += (_begin_payload = _header->encode(msg));
436 #if defined FIX8_PREENCODE_MSG_SUPPORT
439 ::memcpy(msg, _preencode.data(), _payload_len =_preencode_len);
440 msg += _preencode_len;
446 msg += _header->encode(msg);
447 #if defined FIX8_PREENCODE_MSG_SUPPORT
450 ::memcpy(msg, _preencode.data(), _preencode_len);
451 msg += _preencode_len;
460 msg += _trailer->encode(msg);
461 const size_t msgLen(msg - moffs);
462 const size_t hlen(_ctx._preamble_sz +
463 (msgLen < 10 ? 1 : msgLen < 100 ? 2 : msgLen < 1000 ? 3 : msgLen < 10000 ? 4 :
464 msgLen < 100000 ? 5 : msgLen < 1000000 ? 6 : 7));
465 char *hmsg(moffs - hlen);
468 if (!_header->get_begin_string())
471 hmsg += _header->get_begin_string()->encode(hmsg);
473 if (!_header->get_body_length())
477 _header->get_body_length()->set(static_cast<int>(msgLen));
478 hmsg += _header->get_body_length()->encode(hmsg);
480 if (!_trailer->get_check_sum())
482 _trailer->get_check_sum()->set(fmt_chksum(calc_chksum(moffs - hlen, msgLen + hlen)));
484 msg += _trailer->get_check_sum()->encode(msg);
486 #if defined FIX8_CODECTIMING
488 ++_encode_timings._msg_count;
492 const size_t rlen(msg - *hmsg_store);
493 #if defined FIX8_RAW_MSG_SUPPORT
494 _rawmsg.assign(*hmsg_store, rlen);
503 const size_t msgLen(encode(&ptr));
504 to.assign(ptr, msgLen);
511 const string dspacer((depth + 1) * _tabsize,
' ');
512 const BaseMsgEntry *tbme(_ctx._bme.find_ptr(_msgType.c_str()));
514 os << string(depth * _tabsize,
' ') << tbme->
_name <<
" (\"" << _msgType <<
"\")" << endl;
515 for (
const auto& pp : _pos)
517 const BaseEntry *tbe(_ctx.find_be(pp.second->_fnum));
520 os << dspacer << tbe->_name;
521 const unsigned short comp(_fp.getComp(pp.second->_fnum));
523 os <<
" [" << _ctx._cn[comp] <<
']';
524 os <<
" (" << pp.second->_fnum <<
"): ";
526 if (pp.second->_rlm && (idx = (pp.second->get_rlm_idx())) >= 0)
527 os << pp.second->_rlm->_descriptions[idx] <<
" (" << *pp.second <<
')' << endl;
529 os << *pp.second << endl;
530 if (_fp.is_group(pp.second->_fnum) && has_group_count(pp.second))
531 print_group(pp.second->_fnum, os, depth);
543 const string dspacer(depth * _tabsize,
' ');
545 for (
const auto *pp : grpbase->
_msgs)
547 os << dspacer << pp->_msgType <<
" (Repeating group " << cnt <<
'/' << grpbase->
_msgs.size() <<
')' << endl;
548 pp->print(os, depth);
556 Fields::const_iterator fitr(_fields.find(fnum));
557 if (fitr != _fields.end())
559 const BaseEntry *tbe(_ctx.find_be(fnum));
562 os << tbe->_name <<
" (" << fnum <<
"): ";
564 if (fitr->second->_rlm && (idx = (fitr->second->get_rlm_idx())) >= 0)
565 os << fitr->second->_rlm->_descriptions[idx] <<
" (" << *fitr->second <<
')';
568 if (_fp.is_group(fnum) && has_group_count(fitr->second))
569 print_group(fnum, os, 0);
577 Fields::iterator itr(_fields.find(fnum));
578 if (itr != _fields.end())
581 unsigned pos(_fp.getPos(fnum));
582 for (Positions::iterator pitr(_pos.begin()); pitr != _pos.end(); ++pitr)
584 if (pitr->second == old)
591 _pos.insert({pos, with});
602 Fields::iterator itr(_fields.find(fnum));
603 if (itr != _fields.end())
606 unsigned pos(_fp.getPos(fnum, fitr));
607 for (Positions::iterator pitr(_pos.begin()); pitr != _pos.end(); ++pitr)
609 if (pitr->second == old)
616 _pos.insert({pos, with});
627 Fields::iterator itr(_fields.find(fnum));
628 if (itr != _fields.end())
631 for (Positions::iterator pitr(_pos.begin()); pitr != _pos.end(); ++pitr)
633 if (pitr->second == old)
649 Fields::iterator itr(_fields.find(fnum));
650 if (itr != _fields.end())
653 for (Positions::iterator pitr(_pos.begin()); pitr != _pos.end(); ++pitr)
655 if (pitr->second == old)
670 const BaseMsgEntry& bme(_ctx._bme.find_ref(_msgType.c_str()));
674 _header->copy_legal(msg->_header);
675 _trailer->copy_legal(msg->_trailer);
685 os <<
"Null Header" << endl;
690 os <<
"Null Trailer" << endl;
694 #if defined FIX8_CODECTIMING
695 void Message::format_codec_timings(
const f8String& str, ostream& os, codec_timings& ct)
697 os << str <<
": " << setprecision(9) << ct._cpu_used <<
" secs, "
698 << setw(8) << right << ct._msg_count <<
" msgs, "
699 << (ct._cpu_used / ct._msg_count) <<
" secs/msg, "
700 << setprecision(2) << (ct._msg_count / ct._cpu_used) <<
" msgs/sec";
703 void Message::report_codec_timings(
const f8String& tag)
706 ostr.setf(std::ios::showpoint);
707 ostr.setf(std::ios::fixed);
710 format_codec_timings(
"Encode", ostr, _encode_timings);
715 format_codec_timings(
"Decode", ostr, _decode_timings);
724 auto itr(_groups.find(fnum));
725 if (itr != _groups.end())
F8API unsigned move_legal(MessageBase *to, bool force=false)
const IntervalTimer & Calculate()
const MessageSpec * find_group(const CommonGroupMap &globmap, int &vers, unsigned tp, uint32_t key)
An outbound message was missing a header or trailer.
A field was decoded in a message that has already been decoded.
F8API unsigned decode(const f8String &from, unsigned offset, unsigned ignore=0, bool permissive_mode=false)
const unsigned short Common_CheckSum(10)
static unsigned extract_trailer(const f8String &from, f8String &chksum)
const size_t MAX_MSGTYPE_FIELD_LEN(32)
#define FIX8_MAX_FLD_LENGTH
F8API BaseField * remove(const unsigned short fnum, Presence::const_iterator itr)
An inbound message had an invalid (incorrect) checksum.
virtual F8API void print_field(const unsigned short fnum, std::ostream &os) const
Message instantiation table entry.
An invalid field was decoded.
GroupBase * find_group() const
virtual F8API void print(std::ostream &os, int depth=0) const
bool has(const unsigned short field, Presence::const_iterator &itr) const
F8API size_t encode(f8String &to) const
const size_t HEADER_CALC_OFFSET(32)
F8API unsigned copy_legal(MessageBase *to, bool force=false) const
unsigned decode_group(GroupBase *grpbase, const unsigned short fnum, const f8String &from, unsigned s_offset, unsigned ignore)
std::function< Message *(bool)> _do
const Presence & get_presence() const
F8API unsigned check_positions()
virtual F8API void print_group(const unsigned short fnum, std::ostream &os, int depth=0) const
Abstract base class for all repeating groups.
static unsigned extract_header(const f8String &from, char *len, char *mtype)
virtual MessageBase * create_group(bool deepctor=true) const =0
Used for static trait interrogation.
const F8MetaCntx & ctx()
Compiler generated metadata object, accessed through this function.
F8API Message * clone() const
#define FIX8_MAX_MSG_LENGTH
F8API BaseField * replace(const unsigned short fnum, Presence::const_iterator itr, BaseField *with)
F8API size_t encode_group(const unsigned short fnum, std::ostream &to) const
An invalid repeating group was found while attempting to encode a message.
const unsigned short Common_BodyLength(9)
A complete Fix message with header, body and trailer.
static Message * factory(const F8MetaCntx &ctx, const char *from, bool no_chksum=false, bool permissive_mode=false)
bool get(const unsigned short field, FieldTrait::TraitTypes type=FieldTrait::present) const
An invalid message was requested or decoded.
An invalid repeating group field was found while decoding a message (first field is mandatory)...
void check_set_rlm(BaseField *where) const
An invalid field was requested or added.
const unsigned short Common_BeginString(8)
void add_field(const unsigned short fnum, Presence::const_iterator itr, const unsigned pos, BaseField *what, bool check)
The base field class (ABC) for all fields.
static F8API unsigned _tabsize
virtual F8API void print(std::ostream &os, int depth=0) const
F8API size_t encode(std::ostream &to) const
An outbound message was missing a mandatory field.
GroupElement _msgs
vector of repeating messagebase groups
Base class for all fix messages.
const Val * find_ptr(const Key &key) const
High resolution interval timer.