18#include <unordered_map>
28constexpr char SOH =
'\x01';
53 void set(
int tag,
const std::string& value) { fields_[tag] = value; }
60 void set(
int tag,
int value) { fields_[tag] = std::to_string(value); }
69 auto it = fields_.find(tag);
70 if (it == fields_.end()) {
71 throw std::runtime_error(
"Tag not found: " + std::to_string(tag));
92 bool has(
int tag)
const {
93 return fields_.count(tag) > 0;
100 const std::unordered_map<int, std::string>&
get_fields()
const {
106 std::unordered_map<int, std::string> fields_;
145 generate_utc_timestamp(ts,
sizeof(ts));
149 static constexpr std::array<int, 5> kStdHeaderOrder = {
157 std::ostringstream header_rest_ss;
158 for (
int tag : kStdHeaderOrder) {
165 std::string body_str = build_body_from_message(msg);
167 std::string header_rest = header_rest_ss.str();
170 std::size_t body_length_val = header_rest.size() + body_str.size();
174 std::ostringstream prefix_ss;
180 std::string prefix = prefix_ss.str();
183 std::string checksum = calculate_checksum(prefix);
195 const std::string checksum_tag = std::string(1,
SOH) + std::to_string(
tags::CheckSum) +
"=";
196 const size_t checksum_pos = raw.rfind(checksum_tag);
197 if (checksum_pos == std::string::npos) {
198 throw std::runtime_error(
"Tag 10 (Checksum) not found");
200 const std::string prefix = raw.substr(0, checksum_pos + 1);
201 const std::string expected_checksum = raw.substr(checksum_pos + checksum_tag.length(), 3);
202 const std::string actual_checksum = calculate_checksum(prefix);
203 if (expected_checksum != actual_checksum) {
204 throw std::runtime_error(
"Checksum mismatch: expected " + expected_checksum +
", got " + actual_checksum);
211 while ((next_soh = raw.find(
SOH, pos)) != std::string::npos) {
212 const std::string field = raw.substr(pos, next_soh - pos);
217 const size_t eq_pos = field.find(
'=');
218 if (eq_pos == std::string::npos) {
219 throw std::runtime_error(
"Invalid field format: " + field);
221 int tag = std::stoi(field.substr(0, eq_pos));
222 std::string value = field.substr(eq_pos + 1);
229 const size_t body_start_pos = raw.find(
SOH, raw.find(std::to_string(
tags::BodyLength) +
"=")) + 1;
230 const size_t actual_body_len = checksum_pos + 1 - body_start_pos;
231 if (
static_cast<size_t>(body_len_from_msg) != actual_body_len) {
232 throw std::runtime_error(
"BodyLength mismatch: expected " + std::to_string(body_len_from_msg) +
", got " + std::to_string(actual_body_len));
244 std::string build_body_from_message(
const FixMessage& msg)
const {
245 std::ostringstream body;
248 std::vector<int> body_tags;
249 for (
const auto& pair : msg.get_fields()) {
254 body_tags.push_back(pair.first);
257 std::sort(body_tags.begin(), body_tags.end());
259 for (
int tag : body_tags) {
273 std::string calculate_checksum(
const std::string& data)
const {
274 const uint32_t sum = std::accumulate(data.begin(), data.end(), 0U);
275 std::ostringstream oss;
276 oss << std::setfill(
'0') << std::setw(3) << (sum % 256);
287 void generate_utc_timestamp(
char* buf,
size_t buf_size)
const {
288 std::time_t t = std::time(
nullptr);
295 std::strftime(buf, buf_size,
"%Y%m%d-%H:%M:%S", &tm);
FIX 消息编解码器
Definition fix_codec.hpp:133
FixMessage decode(const std::string &raw) const
将 FIX 协议字符串解码为 FixMessage 对象
Definition fix_codec.hpp:193
std::string encode(FixMessage &msg) const
将 FixMessage 编码为 FIX 协议字符串
Definition fix_codec.hpp:142
FIX 消息的面向对象封装
Definition fix_codec.hpp:46
void set(int tag, const std::string &value)
设置字符串类型字段
Definition fix_codec.hpp:53
const std::unordered_map< int, std::string > & get_fields() const
获取所有字段的只读引用
Definition fix_codec.hpp:100
std::string get_string(int tag) const
获取字符串类型字段值
Definition fix_codec.hpp:68
bool has(int tag) const
检查标签是否存在
Definition fix_codec.hpp:92
void set(int tag, int value)
设置整数类型字段
Definition fix_codec.hpp:60
int get_int(int tag) const
获取整数类型字段值
Definition fix_codec.hpp:82
Definition matching_engine.hpp:23
constexpr char SOH
FIX 字段分隔符:ASCII SOH (0x01)
Definition fix_codec.hpp:28