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.