//------------------------------------------------------------------------------------------------- unsigned Message::encode(f8String& to) const { char msg[MAX_MSG_LENGTH], hmsg[MAX_MSG_LENGTH]; size_t sz(0), hsz(0); #if defined CODECTIMING ostringstream gerr; gerr << "encode(" << _msgType << "):"; IntervalTimer itm; #endif if (!_header) throw MissingMessageComponent("header"); Fields::const_iterator fitr(_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(_msgType); _header->encode(msg, sz); MessageBase::encode(msg, sz); if (!_trailer) throw MissingMessageComponent("trailer"); _trailer->encode(msg, sz); const unsigned msgLen(sz); // checksummable msglength if ((fitr = _header->_fields.find(Common_BeginString)) == _header->_fields.end()) throw MissingMandatoryField(Common_BeginString); _header->_fp.clear(Common_BeginString, FieldTrait::suppress); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _header->_fp.set(Common_BeginString, FieldTrait::suppress); // in case we want to reuse #endif if ((fitr = _header->_fields.find(Common_BodyLength)) == _header->_fields.end()) throw MissingMandatoryField(Common_BodyLength); _header->_fp.clear(Common_BodyLength, FieldTrait::suppress); static_cast<body_length *>(fitr->second)->set(msgLen); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _header->_fp.set(Common_BodyLength, FieldTrait::suppress); // in case we want to reuse #endif ::memcpy(hmsg + hsz, msg, sz); hsz += sz; if ((fitr = _trailer->_fields.find(Common_CheckSum)) == _trailer->_fields.end()) throw MissingMandatoryField(Common_CheckSum); static_cast<check_sum *>(fitr->second)->set(fmt_chksum(calc_chksum(hmsg, hsz))); _trailer->_fp.clear(Common_CheckSum, FieldTrait::suppress); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _trailer->_fp.set(Common_CheckSum, FieldTrait::suppress); // in case we want to reuse #endif #if defined CODECTIMING gerr << itm.Calculate(); GlobalLogger::log(gerr.str()); #endif to.assign(hmsg, hsz); return to.size(); }
//------------------------------------------------------------------------------------------------- /// Encode message with minimal copying size_t Message::encode(char **hmsg_store) const { char *moffs(*hmsg_store + HEADER_CALC_OFFSET), *msg(moffs); #if defined CODECTIMING IntervalTimer itm; #endif if (!_header) throw MissingMessageComponent("header"); Fields::const_iterator fitr(_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(_msgType); msg += _header->encode(msg); // start msg += MessageBase::encode(msg); if (!_trailer) throw MissingMessageComponent("trailer"); msg += _trailer->encode(msg); const size_t msgLen(msg - moffs); // checksummable msglength const size_t hlen(_ctx._preamble_sz + (msgLen < 10 ? 1 : msgLen < 100 ? 2 : msgLen < 1000 ? 3 : 4)); char *hmsg(moffs - hlen); *hmsg_store = hmsg; if ((fitr = _header->_fields.find(Common_BeginString)) == _header->_fields.end()) throw MissingMandatoryField(Common_BeginString); _header->_fp.clear(Common_BeginString, FieldTrait::suppress); hmsg += fitr->second->encode(hmsg); #if defined MSGRECYCLING _header->_fp.set(Common_BeginString, FieldTrait::suppress); // in case we want to reuse #endif if ((fitr = _header->_fields.find(Common_BodyLength)) == _header->_fields.end()) throw MissingMandatoryField(Common_BodyLength); _header->_fp.clear(Common_BodyLength, FieldTrait::suppress); static_cast<body_length *>(fitr->second)->set(msgLen); hmsg += fitr->second->encode(hmsg); #if defined MSGRECYCLING _header->_fp.set(Common_BodyLength, FieldTrait::suppress); // in case we want to reuse #endif if ((fitr = _trailer->_fields.find(Common_CheckSum)) == _trailer->_fields.end()) throw MissingMandatoryField(Common_CheckSum); static_cast<check_sum *>(fitr->second)->set(fmt_chksum(calc_chksum(moffs - hlen, msgLen + hlen))); _trailer->_fp.clear(Common_CheckSum, FieldTrait::suppress); msg += fitr->second->encode(msg); #if defined MSGRECYCLING _trailer->_fp.set(Common_CheckSum, FieldTrait::suppress); // in case we want to reuse #endif #if defined CODECTIMING _encode_timings._cpu_used += itm.Calculate().AsDouble(); ++_encode_timings._msg_count; #endif *msg = 0; return msg - *hmsg_store; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from) { Message *msg(0); f8String len, mtype; if (extract_header(from, len, mtype)) { const unsigned mlen(fast_atoi<unsigned>(len.c_str())); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); msg = bme->_create(); #if defined PERMIT_CUSTOM_FIELDS if (ctx._ube) ctx._ube->post_msg_ctor(msg); #endif #if defined CODECTIMING ostringstream gerr; gerr << "decode(" << mtype << "):"; IntervalTimer itm; #endif msg->decode(from); #if defined CODECTIMING gerr << itm.Calculate(); GlobalLogger::log(gerr.str()); #endif static_cast<body_length *>(msg->_header->_fields.find(Common_BodyLength)->second)->set(mlen); Fields::const_iterator fitr(msg->_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!ctx.has_flag(F8MetaCntx::noverifychksum)) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); static_cast<check_sum *>(msg->_trailer->_fields.find(Common_CheckSum)->second)->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } } else { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } return msg; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from) { Message *msg(0); f8String len, mtype; if (extract_header(from, len, mtype)) { const unsigned mlen(fast_atoi<unsigned>(len.c_str())); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); msg = bme->_create(); #if defined PERMIT_CUSTOM_FIELDS if (ctx._ube) ctx._ube->post_msg_ctor(msg); #endif #if defined CODECTIMING ostringstream gerr; gerr << "decode(" << mtype << "):"; IntervalTimer itm; #endif msg->decode(from); #if defined CODECTIMING gerr << itm.Calculate(); GlobalLogger::log(gerr.str()); #endif Fields::const_iterator fitr(msg->_header->_fields.find(Common_BodyLength)); static_cast<body_length *>(fitr->second)->set(mlen); fitr = msg->_header->_fields.find(Common_MsgType); static_cast<msg_type *>(fitr->second)->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif f8String chksum; if (extract_trailer(from, chksum)) { Fields::const_iterator fitr(msg->_trailer->_fields.find(Common_CheckSum)); static_cast<check_sum *>(fitr->second)->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), // chksum value mchkval(calc_chksum(from, 0)); // chksum pos if (chkval != mchkval) throw BadCheckSum(mchkval); } } else { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } return msg; }
//------------------------------------------------------------------------------------------------- /// Encode message with minimal copying size_t Message::encode(char **hmsg_store) const { char *moffs(*hmsg_store + HEADER_CALC_OFFSET), *msg(moffs); #if defined CODECTIMING IntervalTimer itm; #endif if (!_header) throw MissingMessageComponent("header"); _header->get_msg_type()->set(_msgType); msg += _header->encode(msg); // start msg += MessageBase::encode(msg); if (!_trailer) throw MissingMessageComponent("trailer"); msg += _trailer->encode(msg); const size_t msgLen(msg - moffs); // checksummable msglength const size_t hlen(_ctx._preamble_sz + (msgLen < 10 ? 1 : msgLen < 100 ? 2 : msgLen < 1000 ? 3 : msgLen < 10000 ? 4 : msgLen < 100000 ? 5 : msgLen < 1000000 ? 6 : 7)); char *hmsg(moffs - hlen); *hmsg_store = hmsg; if (!_header->get_begin_string()) throw MissingMandatoryField(Common_BeginString); _header->_fp.clear(Common_BeginString, FieldTrait::suppress); hmsg += _header->get_begin_string()->encode(hmsg); if (!_header->get_body_length()) throw MissingMandatoryField(Common_BodyLength); _header->_fp.clear(Common_BodyLength, FieldTrait::suppress); _header->get_body_length()->set(msgLen); hmsg += _header->get_body_length()->encode(hmsg); if (!_trailer->get_check_sum()) throw MissingMandatoryField(Common_CheckSum); _trailer->get_check_sum()->set(fmt_chksum(calc_chksum(moffs - hlen, msgLen + hlen))); _trailer->_fp.clear(Common_CheckSum, FieldTrait::suppress); msg += _trailer->get_check_sum()->encode(msg); #if defined CODECTIMING _encode_timings._cpu_used += itm.Calculate().AsDouble(); ++_encode_timings._msg_count; #endif *msg = 0; return msg - *hmsg_store; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from) { Message *msg(0); char mtype[MAX_MSGTYPE_FIELD_LEN] = {}, len[MAX_MSGTYPE_FIELD_LEN] = {}; if (extract_header(from, len, mtype)) { const unsigned mlen(fast_atoi<unsigned>(len)); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); msg = bme->_create(); #if defined CODECTIMING IntervalTimer itm; #endif msg->decode(from); #if defined CODECTIMING _decode_timings._cpu_used += itm.Calculate().AsDouble(); ++_decode_timings._msg_count; #endif static_cast<body_length *>(msg->_header->_fields.find(Common_BodyLength)->second)->set(mlen); Fields::const_iterator fitr(msg->_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!ctx.has_flag(F8MetaCntx::noverifychksum)) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); static_cast<check_sum *>(msg->_trailer->_fields.find(Common_CheckSum)->second)->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } } else { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } return msg; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from, bool no_chksum, bool permissive_mode) { char mtype[MAX_MSGTYPE_FIELD_LEN] = {}, len[MAX_MSGTYPE_FIELD_LEN] = {}; const size_t hlen(extract_header(from, len, mtype)); if (!hlen) { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } const unsigned mlen(fast_atoi<unsigned>(len)); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); Message *msg(bme->_create._do()); #if defined CODECTIMING IntervalTimer itm; #endif msg->decode(from, hlen, 7, permissive_mode); // skip already decoded mandatory 8, 9, 35 and 10 #if defined CODECTIMING _decode_timings._cpu_used += itm.Calculate().AsDouble(); ++_decode_timings._msg_count; #endif msg->_header->get_body_length()->set(mlen); msg->_header->get_msg_type()->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!no_chksum) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); msg->_trailer->get_check_sum()->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } return msg; }
//------------------------------------------------------------------------------------------------- /// Encode message with minimal copying size_t Message::encode(char **hmsg_store) const { char *moffs(*hmsg_store + HEADER_CALC_OFFSET), *msg(moffs); #if defined FIX8_CODECTIMING IntervalTimer itm; #endif if (!_header) throw MissingMessageComponent("header"); _header->get_msg_type()->set(_msgType); #if defined FIX8_RAW_MSG_SUPPORT msg += (_begin_payload = _header->encode(msg)); // start #if defined FIX8_PREENCODE_MSG_SUPPORT if (_preencode_len) { ::memcpy(msg, _preencode.data(), _payload_len =_preencode_len); msg += _preencode_len; } else #endif msg += (_payload_len = MessageBase::encode(msg)); #else msg += _header->encode(msg); // start #if defined FIX8_PREENCODE_MSG_SUPPORT if (_preencode_len) { ::memcpy(msg, _preencode.data(), _preencode_len); msg += _preencode_len; } else #endif msg += MessageBase::encode(msg); #endif if (!_trailer) throw MissingMessageComponent("trailer"); msg += _trailer->encode(msg); const size_t msgLen(msg - moffs); // checksummable msglength const size_t hlen(_ctx._preamble_sz + (msgLen < 10 ? 1 : msgLen < 100 ? 2 : msgLen < 1000 ? 3 : msgLen < 10000 ? 4 : msgLen < 100000 ? 5 : msgLen < 1000000 ? 6 : 7)); char *hmsg(moffs - hlen); *hmsg_store = hmsg; if (!_header->get_begin_string()) throw MissingMandatoryField(Common_BeginString); _header->_fp.clear(Common_BeginString, FieldTrait::suppress); hmsg += _header->get_begin_string()->encode(hmsg); if (!_header->get_body_length()) throw MissingMandatoryField(Common_BodyLength); _header->_fp.clear(Common_BodyLength, FieldTrait::suppress); _header->get_body_length()->set(static_cast<int>(msgLen)); hmsg += _header->get_body_length()->encode(hmsg); if (!_trailer->get_check_sum()) throw MissingMandatoryField(Common_CheckSum); _trailer->get_check_sum()->set(fmt_chksum(calc_chksum(moffs - hlen, msgLen + hlen))); _trailer->_fp.clear(Common_CheckSum, FieldTrait::suppress); msg += _trailer->get_check_sum()->encode(msg); #if defined FIX8_CODECTIMING _encode_timings._cpu_used += itm.Calculate().AsDouble(); ++_encode_timings._msg_count; #endif *msg = 0; const size_t rlen(msg - *hmsg_store); #if defined FIX8_RAW_MSG_SUPPORT _rawmsg.assign(*hmsg_store, rlen); #endif return rlen; }