#include "ek_ctp_pod.h"
#include "ThostFtdcUserApiStruct.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
namespace {
const UINT kGbkCodePage = 936;
size_t gbk_to_utf8_impl(const char *gbk, size_t n, char *out, size_t out_cap) {
if (out == 0 || out_cap == 0) {
return 0;
}
out[0] = '\0';
if (gbk == 0 || n == 0 || n > (size_t)INT_MAX) {
return 0;
}
const int wide_len = MultiByteToWideChar(kGbkCodePage, MB_ERR_INVALID_CHARS, gbk, (int)n, 0, 0);
if (wide_len <= 0) {
return 0;
}
wchar_t wide_stack[256];
wchar_t *wide = wide_stack;
if ((size_t)wide_len > sizeof(wide_stack) / sizeof(wide_stack[0])) {
wide = (wchar_t *)malloc(sizeof(wchar_t) * (size_t)wide_len);
if (wide == 0) {
return 0;
}
}
size_t written = 0;
if (MultiByteToWideChar(kGbkCodePage, MB_ERR_INVALID_CHARS, gbk, (int)n, wide, wide_len) ==
wide_len) {
const int utf8_len = WideCharToMultiByte(CP_UTF8, 0, wide, wide_len, 0, 0, 0, 0);
if (utf8_len > 0 && (size_t)utf8_len < out_cap &&
WideCharToMultiByte(CP_UTF8, 0, wide, wide_len, out, utf8_len, 0, 0) == utf8_len) {
out[utf8_len] = '\0';
written = (size_t)utf8_len;
}
}
if (wide != wide_stack) {
free(wide);
}
return written;
}
size_t utf8_to_gbk_impl(const char *utf8, char *out, size_t out_cap) {
if (out == 0 || out_cap == 0) {
return 0;
}
out[0] = '\0';
if (utf8 == 0) {
return 0;
}
const size_t n = strlen(utf8);
if (n == 0 || n > (size_t)INT_MAX) {
return 0;
}
const int wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, (int)n, 0, 0);
if (wide_len <= 0) {
return 0;
}
wchar_t *wide = (wchar_t *)malloc(sizeof(wchar_t) * (size_t)wide_len);
if (wide == 0) {
return 0;
}
size_t written = 0;
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, (int)n, wide, wide_len) ==
wide_len) {
const int gbk_len = WideCharToMultiByte(kGbkCodePage, 0, wide, wide_len, 0, 0, 0, 0);
if (gbk_len > 0 && (size_t)gbk_len < out_cap &&
WideCharToMultiByte(kGbkCodePage, 0, wide, wide_len, out, gbk_len, 0, 0) == gbk_len) {
out[gbk_len] = '\0';
written = (size_t)gbk_len;
}
}
free(wide);
return written;
}
char *utf8_to_gbk_alloc(const char *utf8, size_t *len) {
if (len != 0) {
*len = 0;
}
if (utf8 == 0) {
return 0;
}
const size_t n = strlen(utf8);
if (n == 0 || n > (size_t)INT_MAX) {
return 0;
}
const int wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, (int)n, 0, 0);
if (wide_len <= 0) {
return 0;
}
wchar_t *wide = (wchar_t *)malloc(sizeof(wchar_t) * (size_t)wide_len);
if (wide == 0) {
return 0;
}
char *out = 0;
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, (int)n, wide, wide_len) ==
wide_len) {
const int gbk_len = WideCharToMultiByte(kGbkCodePage, 0, wide, wide_len, 0, 0, 0, 0);
if (gbk_len > 0) {
out = (char *)malloc((size_t)gbk_len + 1);
if (out != 0) {
if (WideCharToMultiByte(kGbkCodePage, 0, wide, wide_len, out, gbk_len, 0, 0) !=
gbk_len) {
free(out);
out = 0;
} else {
out[gbk_len] = '\0';
if (len != 0) {
*len = (size_t)gbk_len;
}
}
}
}
}
free(wide);
return out;
}
const char *put_gbk(const char *gbk, size_t n, char *scratch, size_t cap, size_t *offset) {
if (scratch == 0 || offset == 0 || *offset >= cap) {
return "";
}
const size_t at = *offset;
const size_t written = gbk_to_utf8_impl(gbk, n, scratch + at, cap - at);
scratch[at + written] = '\0';
*offset = at + written + 1;
return scratch + at;
}
template <size_t N>
size_t ctp_len(const char (&arr)[N]) {
size_t n = 0;
while (n < N && arr[n] != '\0') {
++n;
}
return n;
}
template <size_t N>
const char *put_array(const char (&arr)[N], char *scratch, size_t cap, size_t *offset) {
return put_gbk(arr, ctp_len(arr), scratch, cap, offset);
}
const char *put_char(char value, char *scratch, size_t cap, size_t *offset) {
if (value == '\0') {
return "";
}
return put_gbk(&value, 1, scratch, cap, offset);
}
template <size_t N>
void set_array(char (&dst)[N], const char *utf8) {
memset(dst, 0, N);
size_t len = 0;
char *gbk = utf8_to_gbk_alloc(utf8, &len);
if (gbk == 0) {
return;
}
size_t n = len;
if (n > N - 1) {
n = N - 1;
size_t boundary = 0;
while (boundary < n) {
const size_t step = ((unsigned char)gbk[boundary] < 0x80) ? 1 : 2;
if (boundary + step > n) {
break;
}
boundary += step;
}
n = boundary;
}
memcpy(dst, gbk, n);
free(gbk);
}
char set_char(const char *utf8) {
size_t len = 0;
char *gbk = utf8_to_gbk_alloc(utf8, &len);
char value = 0;
if (gbk != 0 && len == 1) {
value = gbk[0];
}
free(gbk);
return value;
}
}
extern "C" {
size_t ek_gbk_to_utf8(const char *gbk, size_t gbk_len, char *out, size_t out_cap) {
return gbk_to_utf8_impl(gbk, gbk_len, out, out_cap);
}
size_t ek_utf8_to_gbk(const char *utf8, char *out, size_t out_cap) {
return utf8_to_gbk_impl(utf8, out, out_cap);
}
size_t ek_utf8_to_gbk_truncated(const char *utf8, char *out, size_t out_cap,
int *truncated) {
if (truncated != 0) {
*truncated = 0;
}
if (out == 0 || out_cap == 0) {
return 0;
}
out[0] = '\0';
size_t gbk_len = 0;
char *gbk = utf8_to_gbk_alloc(utf8, &gbk_len);
if (gbk == 0) {
return 0;
}
size_t n = gbk_len;
if (n > out_cap - 1) {
n = out_cap - 1;
size_t boundary = 0;
while (boundary < n) {
const size_t step = ((unsigned char)gbk[boundary] < 0x80) ? 1 : 2;
if (boundary + step > n) {
break;
}
boundary += step;
}
n = boundary;
if (truncated != 0) {
*truncated = 1;
}
}
memcpy(out, gbk, n);
out[n] = '\0';
free(gbk);
return n;
}
void ek_pod_from_error(EkErrorField *out, const CThostFtdcRspInfoField *src, char *scratch,
size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->error_id = src->ErrorID;
out->error_msg = put_array(src->ErrorMsg, scratch, cap, &off);
}
void ek_pod_from_depth(EkDepthMarketData *out, const CThostFtdcDepthMarketDataField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->last_price = src->LastPrice;
out->volume = (double)src->Volume;
out->turnover = src->Turnover;
out->open_interest = src->OpenInterest;
out->upper_limit_price = src->UpperLimitPrice;
out->lower_limit_price = src->LowerLimitPrice;
out->open_price = src->OpenPrice;
out->highest_price = src->HighestPrice;
out->lowest_price = src->LowestPrice;
out->pre_close_price = src->PreClosePrice;
out->bid_price1 = src->BidPrice1;
out->bid_price2 = src->BidPrice2;
out->bid_price3 = src->BidPrice3;
out->bid_price4 = src->BidPrice4;
out->bid_price5 = src->BidPrice5;
out->ask_price1 = src->AskPrice1;
out->ask_price2 = src->AskPrice2;
out->ask_price3 = src->AskPrice3;
out->ask_price4 = src->AskPrice4;
out->ask_price5 = src->AskPrice5;
out->bid_volume1 = (double)src->BidVolume1;
out->bid_volume2 = (double)src->BidVolume2;
out->bid_volume3 = (double)src->BidVolume3;
out->bid_volume4 = (double)src->BidVolume4;
out->bid_volume5 = (double)src->BidVolume5;
out->ask_volume1 = (double)src->AskVolume1;
out->ask_volume2 = (double)src->AskVolume2;
out->ask_volume3 = (double)src->AskVolume3;
out->ask_volume4 = (double)src->AskVolume4;
out->ask_volume5 = (double)src->AskVolume5;
out->update_time = put_array(src->UpdateTime, scratch, cap, &off);
out->update_millisec = (long long)src->UpdateMillisec;
out->trading_day = put_array(src->TradingDay, scratch, cap, &off);
out->action_day = put_array(src->ActionDay, scratch, cap, &off);
}
void ek_pod_from_instrument(EkInstrumentField *out, const CThostFtdcInstrumentField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->instrument_name = put_array(src->InstrumentName, scratch, cap, &off);
out->product_class = put_char(src->ProductClass, scratch, cap, &off);
out->volume_multiple = (double)src->VolumeMultiple;
out->price_tick = src->PriceTick;
out->max_limit_order_volume = (double)src->MaxLimitOrderVolume;
out->min_limit_order_volume = (double)src->MinLimitOrderVolume;
out->max_market_order_volume = (double)src->MaxMarketOrderVolume;
out->min_market_order_volume = (double)src->MinMarketOrderVolume;
out->delivery_year = (long long)src->DeliveryYear;
out->delivery_month = (long long)src->DeliveryMonth;
out->product_id = put_array(src->ProductID, scratch, cap, &off);
out->is_trading = (long long)src->IsTrading;
out->open_date = put_array(src->OpenDate, scratch, cap, &off);
}
void ek_pod_from_order(EkOrderField *out, const CThostFtdcOrderField *src, char *scratch,
size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->order_ref = put_array(src->OrderRef, scratch, cap, &off);
out->front_id = (long long)src->FrontID;
out->session_id = (long long)src->SessionID;
out->order_sys_id = put_array(src->OrderSysID, scratch, cap, &off);
out->direction = put_char(src->Direction, scratch, cap, &off);
out->comb_offset_flag = put_array(src->CombOffsetFlag, scratch, cap, &off);
out->order_price_type = put_char(src->OrderPriceType, scratch, cap, &off);
out->time_condition = put_char(src->TimeCondition, scratch, cap, &off);
out->volume_condition = put_char(src->VolumeCondition, scratch, cap, &off);
out->limit_price = src->LimitPrice;
out->volume_total_original = (double)src->VolumeTotalOriginal;
out->volume_total = (double)src->VolumeTotal;
out->volume_traded = (double)src->VolumeTraded;
out->order_status = put_char(src->OrderStatus, scratch, cap, &off);
out->insert_date = put_array(src->InsertDate, scratch, cap, &off);
out->insert_time = put_array(src->InsertTime, scratch, cap, &off);
}
void ek_pod_from_trade(EkTradeField *out, const CThostFtdcTradeField *src, char *scratch,
size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->order_sys_id = put_array(src->OrderSysID, scratch, cap, &off);
out->trade_id = put_array(src->TradeID, scratch, cap, &off);
out->direction = put_char(src->Direction, scratch, cap, &off);
out->offset_flag = put_char(src->OffsetFlag, scratch, cap, &off);
out->price = src->Price;
out->volume = (double)src->Volume;
out->trade_date = put_array(src->TradeDate, scratch, cap, &off);
out->trade_time = put_array(src->TradeTime, scratch, cap, &off);
}
void ek_pod_from_position(EkInvestorPositionField *out, const CThostFtdcInvestorPositionField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->posi_direction = put_char(src->PosiDirection, scratch, cap, &off);
out->yd_position = (double)src->YdPosition;
out->position = (double)src->Position;
out->today_position = (double)src->TodayPosition;
out->position_cost = src->PositionCost;
out->position_profit = src->PositionProfit;
out->short_frozen = (double)src->ShortFrozen;
out->long_frozen = (double)src->LongFrozen;
}
void ek_pod_from_account(EkTradingAccountField *out, const CThostFtdcTradingAccountField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->account_id = put_array(src->AccountID, scratch, cap, &off);
out->balance = src->Balance;
out->frozen_margin = src->FrozenMargin;
out->frozen_cash = src->FrozenCash;
out->frozen_commission = src->FrozenCommission;
out->available = src->Available;
}
void ek_pod_from_input_order(EkInputOrder *out, const CThostFtdcInputOrderField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->limit_price = src->LimitPrice;
out->volume_total_original = (long long)src->VolumeTotalOriginal;
out->order_price_type = put_char(src->OrderPriceType, scratch, cap, &off);
out->direction = put_char(src->Direction, scratch, cap, &off);
out->comb_offset_flag = put_array(src->CombOffsetFlag, scratch, cap, &off);
out->order_ref = put_array(src->OrderRef, scratch, cap, &off);
out->investor_id = put_array(src->InvestorID, scratch, cap, &off);
out->user_id = put_array(src->UserID, scratch, cap, &off);
out->broker_id = put_array(src->BrokerID, scratch, cap, &off);
out->comb_hedge_flag = put_array(src->CombHedgeFlag, scratch, cap, &off);
out->contingent_condition = put_char(src->ContingentCondition, scratch, cap, &off);
out->force_close_reason = put_char(src->ForceCloseReason, scratch, cap, &off);
out->is_auto_suspend = src->IsAutoSuspend;
out->time_condition = put_char(src->TimeCondition, scratch, cap, &off);
out->volume_condition = put_char(src->VolumeCondition, scratch, cap, &off);
out->min_volume = (long long)src->MinVolume;
}
void ek_pod_from_input_order_action(EkInputOrderAction *out,
const CThostFtdcInputOrderActionField *src, char *scratch,
size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->order_ref = put_array(src->OrderRef, scratch, cap, &off);
out->front_id = (long long)src->FrontID;
out->session_id = (long long)src->SessionID;
out->action_flag = put_char(src->ActionFlag, scratch, cap, &off);
out->broker_id = put_array(src->BrokerID, scratch, cap, &off);
out->investor_id = put_array(src->InvestorID, scratch, cap, &off);
}
void ek_pod_to_input_order(CThostFtdcInputOrderField *dst, const EkInputOrder *src) {
if (dst == 0) {
return;
}
memset(dst, 0, sizeof(*dst));
if (src == 0) {
return;
}
set_array(dst->InstrumentID, src->instrument_id);
set_array(dst->ExchangeID, src->exchange_id);
dst->LimitPrice = src->limit_price;
dst->VolumeTotalOriginal = (int)src->volume_total_original;
dst->OrderPriceType = set_char(src->order_price_type);
dst->Direction = set_char(src->direction);
set_array(dst->CombOffsetFlag, src->comb_offset_flag);
set_array(dst->OrderRef, src->order_ref);
set_array(dst->InvestorID, src->investor_id);
set_array(dst->UserID, src->user_id);
set_array(dst->BrokerID, src->broker_id);
set_array(dst->CombHedgeFlag, src->comb_hedge_flag);
dst->ContingentCondition = set_char(src->contingent_condition);
dst->ForceCloseReason = set_char(src->force_close_reason);
dst->IsAutoSuspend = src->is_auto_suspend;
dst->TimeCondition = set_char(src->time_condition);
dst->VolumeCondition = set_char(src->volume_condition);
dst->MinVolume = (int)src->min_volume;
}
void ek_pod_to_input_order_action(CThostFtdcInputOrderActionField *dst,
const EkInputOrderAction *src) {
if (dst == 0) {
return;
}
memset(dst, 0, sizeof(*dst));
if (src == 0) {
return;
}
set_array(dst->InstrumentID, src->instrument_id);
set_array(dst->ExchangeID, src->exchange_id);
set_array(dst->OrderRef, src->order_ref);
dst->FrontID = (int)src->front_id;
dst->SessionID = (int)src->session_id;
dst->ActionFlag = set_char(src->action_flag);
set_array(dst->BrokerID, src->broker_id);
set_array(dst->InvestorID, src->investor_id);
}
int ek_pod_sizeof_error(void) {
return (int)sizeof(EkErrorField);
}
int ek_pod_sizeof_depth(void) {
return (int)sizeof(EkDepthMarketData);
}
int ek_pod_sizeof_instrument(void) {
return (int)sizeof(EkInstrumentField);
}
int ek_pod_sizeof_order(void) {
return (int)sizeof(EkOrderField);
}
int ek_pod_sizeof_trade(void) {
return (int)sizeof(EkTradeField);
}
int ek_pod_sizeof_position(void) {
return (int)sizeof(EkInvestorPositionField);
}
int ek_pod_sizeof_account(void) {
return (int)sizeof(EkTradingAccountField);
}
int ek_pod_sizeof_input_order(void) {
return (int)sizeof(EkInputOrder);
}
int ek_pod_sizeof_input_order_action(void) {
return (int)sizeof(EkInputOrderAction);
}
void ek_pod_selftest_error(EkErrorField *out, char *scratch, size_t cap) {
CThostFtdcRspInfoField src;
memset(&src, 0, sizeof(src));
src.ErrorID = 2001;
set_array(src.ErrorMsg, "s2");
ek_pod_from_error(out, &src, scratch, cap);
}
void ek_pod_selftest_depth(EkDepthMarketData *out, char *scratch, size_t cap) {
CThostFtdcDepthMarketDataField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
src.LastPrice = 2.0;
src.Volume = 3;
src.Turnover = 4.0;
src.OpenInterest = 5.0;
src.UpperLimitPrice = 6.0;
src.LowerLimitPrice = 7.0;
src.OpenPrice = 8.0;
src.HighestPrice = 9.0;
src.LowestPrice = 10.0;
src.PreClosePrice = 11.0;
src.BidPrice1 = 12.0;
src.BidPrice2 = 13.0;
src.BidPrice3 = 14.0;
src.BidPrice4 = 15.0;
src.BidPrice5 = 16.0;
src.AskPrice1 = 17.0;
src.AskPrice2 = 18.0;
src.AskPrice3 = 19.0;
src.AskPrice4 = 20.0;
src.AskPrice5 = 21.0;
src.BidVolume1 = 22;
src.BidVolume2 = 23;
src.BidVolume3 = 24;
src.BidVolume4 = 25;
src.BidVolume5 = 26;
src.AskVolume1 = 27;
src.AskVolume2 = 28;
src.AskVolume3 = 29;
src.AskVolume4 = 30;
src.AskVolume5 = 31;
set_array(src.UpdateTime, "s32");
src.UpdateMillisec = 1033;
set_array(src.TradingDay, "s34");
set_array(src.ActionDay, "s35");
set_array(src.ExchangeID, "s36");
ek_pod_from_depth(out, &src, scratch, cap);
}
void ek_pod_selftest_instrument(EkInstrumentField *out, char *scratch, size_t cap) {
CThostFtdcInstrumentField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
set_array(src.ExchangeID, "s2");
set_array(src.InstrumentName, "s3");
src.ProductClass = 'E';
src.VolumeMultiple = 5;
src.PriceTick = 6.0;
src.MaxLimitOrderVolume = 7;
src.MinLimitOrderVolume = 8;
src.MaxMarketOrderVolume = 9;
src.MinMarketOrderVolume = 10;
src.DeliveryYear = 1011;
src.DeliveryMonth = 1012;
set_array(src.ProductID, "s13");
src.IsTrading = 1014;
ek_pod_from_instrument(out, &src, scratch, cap);
}
void ek_pod_selftest_order(EkOrderField *out, char *scratch, size_t cap) {
CThostFtdcOrderField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
set_array(src.OrderRef, "s2");
src.FrontID = 1003;
src.SessionID = 1004;
set_array(src.OrderSysID, "s5");
src.Direction = 'G';
set_array(src.CombOffsetFlag, "s7");
src.OrderPriceType = 'I';
src.TimeCondition = 'J';
src.VolumeCondition = 'K';
src.LimitPrice = 11.0;
src.VolumeTotalOriginal = 12;
src.VolumeTotal = 13;
src.VolumeTraded = 14;
src.OrderStatus = 'P';
set_array(src.InsertDate, "s16");
set_array(src.InsertTime, "s17");
ek_pod_from_order(out, &src, scratch, cap);
}
void ek_pod_selftest_trade(EkTradeField *out, char *scratch, size_t cap) {
CThostFtdcTradeField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
set_array(src.OrderSysID, "s2");
set_array(src.TradeID, "s3");
src.Direction = 'E';
src.OffsetFlag = 'F';
src.Price = 6.0;
src.Volume = 7;
set_array(src.TradeDate, "s8");
set_array(src.TradeTime, "s9");
ek_pod_from_trade(out, &src, scratch, cap);
}
void ek_pod_selftest_position(EkInvestorPositionField *out, char *scratch, size_t cap) {
CThostFtdcInvestorPositionField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
src.PosiDirection = 'C';
src.YdPosition = 3;
src.Position = 4;
src.TodayPosition = 5;
src.PositionCost = 6.0;
src.PositionProfit = 7.0;
src.ShortFrozen = 8;
src.LongFrozen = 9;
ek_pod_from_position(out, &src, scratch, cap);
}
void ek_pod_selftest_account(EkTradingAccountField *out, char *scratch, size_t cap) {
CThostFtdcTradingAccountField src;
memset(&src, 0, sizeof(src));
set_array(src.AccountID, "s1");
src.Balance = 2.0;
src.FrozenMargin = 3.0;
src.FrozenCash = 4.0;
src.FrozenCommission = 5.0;
src.Available = 6.0;
ek_pod_from_account(out, &src, scratch, cap);
}
void ek_pod_selftest_input_order(EkInputOrder *out, char *scratch, size_t cap) {
CThostFtdcInputOrderField src;
memset(&src, 0, sizeof(src));
set_array(src.InstrumentID, "s1");
set_array(src.ExchangeID, "s2");
src.LimitPrice = 3.0;
src.VolumeTotalOriginal = 1004;
src.OrderPriceType = 'F';
src.Direction = 'G';
set_array(src.CombOffsetFlag, "s7");
set_array(src.OrderRef, "s8");
set_array(src.InvestorID, "s9");
set_array(src.UserID, "s10");
set_array(src.BrokerID, "s11");
set_array(src.CombHedgeFlag, "s12");
src.ContingentCondition = 'N';
src.ForceCloseReason = 'O';
src.IsAutoSuspend = 2015;
src.TimeCondition = 'Q';
src.VolumeCondition = 'R';
src.MinVolume = 1018;
ek_pod_from_input_order(out, &src, scratch, cap);
}
void ek_pod_selftest_io_roundtrip_input_order(const EkInputOrder *in, EkInputOrder *out,
char *scratch, size_t cap) {
CThostFtdcInputOrderField ctp;
memset(&ctp, 0, sizeof(ctp));
ek_pod_to_input_order(&ctp, in);
ek_pod_from_input_order(out, &ctp, scratch, cap);
}
void ek_pod_selftest_io_roundtrip_input_order_action(const EkInputOrderAction *in,
EkInputOrderAction *out, char *scratch,
size_t cap) {
CThostFtdcInputOrderActionField ctp;
memset(&ctp, 0, sizeof(ctp));
ek_pod_to_input_order_action(&ctp, in);
ek_pod_from_input_order_action(out, &ctp, scratch, cap);
}
int ek_ctp_verify_input_order_action(const EkInputOrderAction *in) {
if (in == 0) {
return -1;
}
CThostFtdcInputOrderActionField got;
memset(&got, 0, sizeof(got));
ek_pod_to_input_order_action(&got, in);
CThostFtdcInputOrderActionField exp;
memset(&exp, 0, sizeof(exp));
set_array(exp.InstrumentID, in->instrument_id);
set_array(exp.ExchangeID, in->exchange_id);
set_array(exp.OrderRef, in->order_ref);
exp.FrontID = (int)in->front_id;
exp.SessionID = (int)in->session_id;
exp.ActionFlag = set_char(in->action_flag);
set_array(exp.BrokerID, in->broker_id);
set_array(exp.InvestorID, in->investor_id);
if (strcmp(got.InstrumentID, exp.InstrumentID) != 0) {
return 1;
}
if (strcmp(got.ExchangeID, exp.ExchangeID) != 0) {
return 2;
}
if (strcmp(got.OrderRef, exp.OrderRef) != 0) {
return 3;
}
if (got.FrontID != exp.FrontID) {
return 4;
}
if (got.SessionID != exp.SessionID) {
return 5;
}
if (got.ActionFlag != exp.ActionFlag) {
return 6;
}
if (strcmp(got.BrokerID, exp.BrokerID) != 0) {
return 7;
}
if (strcmp(got.InvestorID, exp.InvestorID) != 0) {
return 8;
}
return 0;
}
void ek_pod_from_instrument_margin_rate(EkInstrumentMarginRate *out,
const CThostFtdcInstrumentMarginRateField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->investor_range = put_char(src->InvestorRange, scratch, cap, &off);
out->broker_id = put_array(src->BrokerID, scratch, cap, &off);
out->investor_id = put_array(src->InvestorID, scratch, cap, &off);
out->hedge_flag = put_char(src->HedgeFlag, scratch, cap, &off);
out->long_margin_ratio_by_money = src->LongMarginRatioByMoney;
out->long_margin_ratio_by_volume = src->LongMarginRatioByVolume;
out->short_margin_ratio_by_money = src->ShortMarginRatioByMoney;
out->short_margin_ratio_by_volume = src->ShortMarginRatioByVolume;
out->is_relative = src->IsRelative;
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->invest_unit_id = put_array(src->InvestUnitID, scratch, cap, &off);
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
}
void ek_pod_from_instrument_commission_rate(EkInstrumentCommissionRate *out,
const CThostFtdcInstrumentCommissionRateField *src,
char *scratch, size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->investor_range = put_char(src->InvestorRange, scratch, cap, &off);
out->broker_id = put_array(src->BrokerID, scratch, cap, &off);
out->investor_id = put_array(src->InvestorID, scratch, cap, &off);
out->open_ratio_by_money = src->OpenRatioByMoney;
out->open_ratio_by_volume = src->OpenRatioByVolume;
out->close_ratio_by_money = src->CloseRatioByMoney;
out->close_ratio_by_volume = src->CloseRatioByVolume;
out->close_today_ratio_by_money = src->CloseTodayRatioByMoney;
out->close_today_ratio_by_volume = src->CloseTodayRatioByVolume;
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->biz_type = put_char(src->BizType, scratch, cap, &off);
out->invest_unit_id = put_array(src->InvestUnitID, scratch, cap, &off);
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
}
void ek_pod_from_instrument_status(EkInstrumentStatus *out,
const CThostFtdcInstrumentStatusField *src, char *scratch,
size_t cap) {
if (out == 0) {
return;
}
memset(out, 0, sizeof(*out));
if (src == 0) {
return;
}
size_t off = 0;
out->exchange_id = put_array(src->ExchangeID, scratch, cap, &off);
out->settlement_group_id = put_array(src->SettlementGroupID, scratch, cap, &off);
out->instrument_status = put_char(src->InstrumentStatus, scratch, cap, &off);
out->trading_segment_sn = src->TradingSegmentSN;
out->enter_time = put_array(src->EnterTime, scratch, cap, &off);
out->enter_reason = put_char(src->EnterReason, scratch, cap, &off);
out->exchange_inst_id = put_array(src->ExchangeInstID, scratch, cap, &off);
out->instrument_id = put_array(src->InstrumentID, scratch, cap, &off);
}
void ek_pod_to_qry_instrument_margin_rate(CThostFtdcQryInstrumentMarginRateField *dst,
const EkQryInstrumentMarginRate *src) {
if (dst == 0) {
return;
}
memset(dst, 0, sizeof(*dst));
if (src == 0) {
return;
}
set_array(dst->BrokerID, src->broker_id);
set_array(dst->InvestorID, src->investor_id);
dst->HedgeFlag = set_char(src->hedge_flag);
set_array(dst->ExchangeID, src->exchange_id);
set_array(dst->InvestUnitID, src->invest_unit_id);
set_array(dst->InstrumentID, src->instrument_id);
}
void ek_pod_to_qry_instrument_commission_rate(CThostFtdcQryInstrumentCommissionRateField *dst,
const EkQryInstrumentCommissionRate *src) {
if (dst == 0) {
return;
}
memset(dst, 0, sizeof(*dst));
if (src == 0) {
return;
}
set_array(dst->BrokerID, src->broker_id);
set_array(dst->InvestorID, src->investor_id);
set_array(dst->ExchangeID, src->exchange_id);
set_array(dst->InvestUnitID, src->invest_unit_id);
set_array(dst->InstrumentID, src->instrument_id);
}
int ek_pod_sizeof_margin_rate(void) {
return (int)sizeof(EkInstrumentMarginRate);
}
int ek_pod_sizeof_commission_rate(void) {
return (int)sizeof(EkInstrumentCommissionRate);
}
int ek_pod_sizeof_instrument_status(void) {
return (int)sizeof(EkInstrumentStatus);
}
int ek_pod_sizeof_qry_margin_rate(void) {
return (int)sizeof(EkQryInstrumentMarginRate);
}
int ek_pod_sizeof_qry_commission_rate(void) {
return (int)sizeof(EkQryInstrumentCommissionRate);
}
void ek_pod_selftest_margin_rate(EkInstrumentMarginRate *out, char *scratch,
size_t cap) {
CThostFtdcInstrumentMarginRateField src;
memset(&src, 0, sizeof(src));
src.InvestorRange = 'B';
set_array(src.BrokerID, "s2");
set_array(src.InvestorID, "s3");
src.HedgeFlag = 'E';
src.LongMarginRatioByMoney = 5.0;
src.LongMarginRatioByVolume = 6.0;
src.ShortMarginRatioByMoney = 7.0;
src.ShortMarginRatioByVolume = 8.0;
src.IsRelative = 2009;
set_array(src.ExchangeID, "s10");
set_array(src.InvestUnitID, "s11");
set_array(src.InstrumentID, "s12");
ek_pod_from_instrument_margin_rate(out, &src, scratch, cap);
}
void ek_pod_selftest_commission_rate(EkInstrumentCommissionRate *out, char *scratch,
size_t cap) {
CThostFtdcInstrumentCommissionRateField src;
memset(&src, 0, sizeof(src));
src.InvestorRange = 'B';
set_array(src.BrokerID, "s2");
set_array(src.InvestorID, "s3");
src.OpenRatioByMoney = 4.0;
src.OpenRatioByVolume = 5.0;
src.CloseRatioByMoney = 6.0;
src.CloseRatioByVolume = 7.0;
src.CloseTodayRatioByMoney = 8.0;
src.CloseTodayRatioByVolume = 9.0;
set_array(src.ExchangeID, "s10");
src.BizType = 'L';
set_array(src.InvestUnitID, "s12");
set_array(src.InstrumentID, "s13");
ek_pod_from_instrument_commission_rate(out, &src, scratch, cap);
}
void ek_pod_selftest_instrument_status(EkInstrumentStatus *out, char *scratch, size_t cap) {
CThostFtdcInstrumentStatusField src;
memset(&src, 0, sizeof(src));
set_array(src.ExchangeID, "s1");
set_array(src.SettlementGroupID, "s2");
src.InstrumentStatus = 'D';
src.TradingSegmentSN = 2004;
set_array(src.EnterTime, "s5");
src.EnterReason = 'G';
set_array(src.ExchangeInstID, "s7");
set_array(src.InstrumentID, "s8");
ek_pod_from_instrument_status(out, &src, scratch, cap);
}
int ek_ctp_verify_qry_margin_rate(const EkQryInstrumentMarginRate *in) {
if (in == 0) {
return -1;
}
CThostFtdcQryInstrumentMarginRateField got;
memset(&got, 0, sizeof(got));
ek_pod_to_qry_instrument_margin_rate(&got, in);
CThostFtdcQryInstrumentMarginRateField exp;
memset(&exp, 0, sizeof(exp));
set_array(exp.BrokerID, in->broker_id);
set_array(exp.InvestorID, in->investor_id);
exp.HedgeFlag = set_char(in->hedge_flag);
set_array(exp.ExchangeID, in->exchange_id);
set_array(exp.InvestUnitID, in->invest_unit_id);
set_array(exp.InstrumentID, in->instrument_id);
if (strcmp(got.BrokerID, exp.BrokerID) != 0) {
return 1;
}
if (strcmp(got.InvestorID, exp.InvestorID) != 0) {
return 2;
}
if (got.HedgeFlag != exp.HedgeFlag) {
return 3;
}
if (strcmp(got.ExchangeID, exp.ExchangeID) != 0) {
return 4;
}
if (strcmp(got.InvestUnitID, exp.InvestUnitID) != 0) {
return 5;
}
if (strcmp(got.InstrumentID, exp.InstrumentID) != 0) {
return 6;
}
return 0;
}
int ek_ctp_verify_qry_commission_rate(const EkQryInstrumentCommissionRate *in) {
if (in == 0) {
return -1;
}
CThostFtdcQryInstrumentCommissionRateField got;
memset(&got, 0, sizeof(got));
ek_pod_to_qry_instrument_commission_rate(&got, in);
CThostFtdcQryInstrumentCommissionRateField exp;
memset(&exp, 0, sizeof(exp));
set_array(exp.BrokerID, in->broker_id);
set_array(exp.InvestorID, in->investor_id);
set_array(exp.ExchangeID, in->exchange_id);
set_array(exp.InvestUnitID, in->invest_unit_id);
set_array(exp.InstrumentID, in->instrument_id);
if (strcmp(got.BrokerID, exp.BrokerID) != 0) {
return 1;
}
if (strcmp(got.InvestorID, exp.InvestorID) != 0) {
return 2;
}
if (strcmp(got.ExchangeID, exp.ExchangeID) != 0) {
return 3;
}
if (strcmp(got.InvestUnitID, exp.InvestUnitID) != 0) {
return 4;
}
if (strcmp(got.InstrumentID, exp.InstrumentID) != 0) {
return 5;
}
return 0;
}
}