Skip to content

Commit 8a86fb4

Browse files
authored
Merge pull request #35 from mkipnis/misc_1025
fix_ws_proxy - initial check-in
2 parents e98d57a + 55497e6 commit 8a86fb4

35 files changed

+8764
-13
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ add_subdirectory( FIXGateway/src )
3131
add_subdirectory( DataService/src )
3232
add_subdirectory( MatchingEngine/src )
3333
add_subdirectory( LatencyTest )
34-
add_subdirectory( MiscClients/cpp_ws_reactjs/oms )
34+
add_subdirectory( MiscClients/cpp_ws_reactjs/fix_ws_proxy )
3535

3636
install(DIRECTORY ${CMAKE_SOURCE_DIR}/MiscATS/
3737
DESTINATION MiscATS

Common/fix_json_converter.h

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (C) Mike Kipnis - DistributedATS
2+
#pragma once
3+
4+
#include <quickfix/Message.h>
5+
#include <quickfix/FieldMap.h>
6+
#include <boost/json.hpp>
7+
#include <string>
8+
#include <sstream>
9+
10+
namespace distributed_ats {
11+
namespace fix_json {
12+
13+
// Convert a FieldMap (Header, Body, or Trailer) to JSON object (recursive)
14+
inline boost::json::object field_map_to_json(const FIX::FieldMap& map)
15+
{
16+
boost::json::object json_obj;
17+
18+
// --- Fields ---
19+
for (FIX::FieldMap::iterator it = const_cast<FIX::FieldMap&>(map).begin();
20+
it != const_cast<FIX::FieldMap&>(map).end(); ++it)
21+
{
22+
const FIX::FieldBase& field = *it;
23+
int tag = field.getTag();
24+
json_obj[std::to_string(tag)] = field.getString();
25+
}
26+
27+
// --- Groups (repeating groups) ---
28+
const FIX::FieldMap::Groups& group_maps = map.groups();
29+
for (auto group_it = group_maps.begin(); group_it != group_maps.end(); ++group_it)
30+
{
31+
int group_tag = group_it->first;
32+
const std::vector<FIX::FieldMap*>& group_vector = group_it->second;
33+
34+
boost::json::array json_group_array;
35+
for (auto* group_map : group_vector)
36+
{
37+
json_group_array.push_back(field_map_to_json(*group_map));
38+
}
39+
40+
json_obj[std::to_string(group_tag)] = std::move(json_group_array);
41+
}
42+
43+
return json_obj;
44+
}
45+
46+
// Convert entire FIX message to JSON
47+
inline boost::json::object fix_to_json(const FIX::Message& message)
48+
{
49+
boost::json::object json_root;
50+
51+
json_root["Header"] = field_map_to_json(message.getHeader());
52+
json_root["Body"] = field_map_to_json(message);
53+
json_root["Trailer"] = field_map_to_json(message.getTrailer());
54+
55+
return json_root;
56+
}
57+
58+
// Helper: convert JSON object to FieldMap (recursive)
59+
inline void json_to_field_map(const boost::json::object& json_obj, FIX::FieldMap& map)
60+
{
61+
for (auto& kv : json_obj)
62+
{
63+
const std::string& key = kv.key();
64+
const boost::json::value& value = kv.value();
65+
int tag = std::stoi(key);
66+
67+
if (value.is_string())
68+
{
69+
map.setField(FIX::StringField(tag, value.as_string().c_str()));
70+
}
71+
else if (value.is_array())
72+
{
73+
const boost::json::array& arr = value.as_array();
74+
for (auto& item : arr)
75+
{
76+
if (!item.is_object()) continue;
77+
FIX::Group group(tag, 0); // 0 used as placeholder delimiter
78+
json_to_field_map(item.as_object(), group);
79+
map.addGroup(tag, group); // FIX: addGroup(tag, group)
80+
}
81+
}
82+
else
83+
{
84+
// Convert other JSON types to string
85+
std::ostringstream oss;
86+
oss << value;
87+
map.setField(FIX::StringField(tag, oss.str()));
88+
}
89+
}
90+
}
91+
92+
// Convert JSON to FIX::Message
93+
inline FIX::Message json_to_fix(const boost::json::object& json_msg)
94+
{
95+
FIX::Message message;
96+
97+
if (json_msg.if_contains("Header"))
98+
json_to_field_map(json_msg.at("Header").as_object(), message.getHeader());
99+
100+
if (json_msg.if_contains("Body"))
101+
json_to_field_map(json_msg.at("Body").as_object(), message);
102+
103+
if (json_msg.if_contains("Trailer"))
104+
json_to_field_map(json_msg.at("Trailer").as_object(), message.getTrailer());
105+
106+
return message;
107+
}
108+
109+
// Helper: JSON string → FIX::Message
110+
inline FIX::Message json_to_fix(const std::string& json_str)
111+
{
112+
boost::json::value parsed = boost::json::parse(json_str);
113+
if (!parsed.is_object())
114+
throw std::runtime_error("Invalid JSON format for FIX message");
115+
116+
return json_to_fix(parsed.as_object());
117+
}
118+
119+
// Helper: FIX::Message → JSON string
120+
inline std::string fix_to_json_string(const FIX::Message& message)
121+
{
122+
boost::json::object json_obj = fix_to_json(message);
123+
return boost::json::serialize(json_obj);
124+
}
125+
126+
} // namespace fix_json
127+
} // namespace distributed_ats

MiscClients/cpp_ws_reactjs/oms/CMakeLists.txt renamed to MiscClients/cpp_ws_reactjs/fix_ws_proxy/CMakeLists.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.12.4)
22

3-
project(oms)
3+
project(fix_ws_proxy)
44

55
message(STATUS "Current source dir: ${CMAKE_CURRENT_SOURCE_DIR}")
66

@@ -16,15 +16,18 @@ link_directories(${LOG4CXX_LIBRARY_DIR})
1616
include_directories(${Boost_INCLUDE_DIR})
1717
link_directories(${Boost_LIBRARY_DIRS})
1818

19-
file(GLOB OMS_SRC *.cpp)
20-
add_executable(oms ${OMS_SRC})
19+
file(GLOB FIX_WS_SRC *.cpp)
20+
add_executable(fix_ws_proxy ${FIX_WS_SRC})
2121

22-
find_package(Boost REQUIRED COMPONENTS program_options)
22+
find_package(Boost REQUIRED COMPONENTS program_options thread chrono json)
2323
include_directories(${Boost_INCLUDE_DIRS})
2424

25-
target_link_libraries(oms
25+
target_link_libraries(fix_ws_proxy
2626
PRIVATE
2727
quickfix
2828
log4cxx
2929
Boost::program_options
30+
Boost::thread
31+
Boost::json
32+
Boost::chrono
3033
)

0 commit comments

Comments
 (0)