Files
QTradeProgram/cleaned_source_code/FTAPI/tool.h
2026-02-25 23:01:42 +08:00

191 lines
5.0 KiB
C++

#pragma once
#ifdef _WIN32
#include <windows.h>
#else
#include <time.h>
#include <semaphore.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <stdint.h>
#include <sstream>
#include <string>
#include <stdlib.h>
using namespace std;
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include "Include_FTAPI.h"
#include "Include_3rd_protobuf.h"
using namespace google;
using namespace Futu;
#pragma warning(disable:4100)
#pragma warning(disable:4189)
inline void ProtoBufToBodyData(const protobuf::Message& pbObj, string& strBody)
{
protobuf::util::JsonPrintOptions ops;
ops.add_whitespace = true;
ops.always_print_enums_as_ints = true;
protobuf::util::Status status = MessageToJsonString(pbObj, &strBody, ops);
if (status.error_code() != protobuf::util::error::OK)
{
strBody.clear();
}
}
inline void ProtoBufToBodyData_Ex(const protobuf::Message& pbObj, std::string& strBody) {
thread_local static std::string buffer;
buffer.clear();
protobuf::util::JsonPrintOptions ops;
ops.add_whitespace = false;
ops.preserve_proto_field_names = true;
ops.always_print_primitive_fields = false;
if (protobuf::util::MessageToJsonString(pbObj, &buffer, ops).ok()) {
strBody.swap(buffer);
}
else {
strBody.clear();
}
}
inline void ProtoBufToBodyData_Binary(const protobuf::Message& pbObj, std::string& strBody) noexcept {
thread_local static std::string buffer;
pbObj.SerializeToString(&buffer);
strBody.swap(buffer);
buffer.clear();
}
inline void FastSerializeProto(const protobuf::Message& pbObj, std::string& strBody) noexcept {
thread_local static struct {
std::string buffer;
size_t last_capacity = 0;
} tls_pool;
const size_t need_size = pbObj.ByteSizeLong();
if (tls_pool.last_capacity < need_size * 1.2) {
tls_pool.buffer.reserve(std::max(need_size * 2, size_t(4096)));
tls_pool.last_capacity = tls_pool.buffer.capacity();
}
tls_pool.buffer.clear();
pbObj.SerializeToString(&tls_pool.buffer);
strBody.swap(tls_pool.buffer);
}
#if defined(__GNUC__) || defined(__clang__)
# define MY_PREDICT_FALSE(x) (__builtin_expect(!!(x), 0))
# define MY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
# define MY_PREDICT_FALSE(x) (x)
# define MY_PREDICT_TRUE(x) (x)
#endif
inline bool FastDeserializeProto(const std::string& strBody, protobuf::Message& pbObj) noexcept {
protobuf::io::ArrayInputStream raw_input(strBody.data(), strBody.size());
protobuf::io::CodedInputStream coded_input(&raw_input);
coded_input.SetTotalBytesLimit(100 * 1024 * 1024, 50 * 1024 * 1024);
if (MY_PREDICT_FALSE(!pbObj.ParseFromCodedStream(&coded_input))) {
pbObj.Clear();
return false;
}
if (MY_PREDICT_FALSE(!pbObj.IsInitialized())) {
pbObj.Clear();
return false;
}
return true;
}
#if defined(_WIN32)
inline string UTF8ToGBK(const string &strUTF8)
{
int nLen = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
wchar_t* wszGBK = new wchar_t[nLen + 1];
memset(wszGBK, 0, nLen * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, wszGBK, nLen);
nLen = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
char* szGBK = new char[nLen + 1];
memset(szGBK, 0, nLen + 1);
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, nLen, NULL, NULL);
string strGBK(szGBK);
if (wszGBK) delete[] wszGBK;
if (szGBK) delete[] szGBK;
return strGBK;
}
#endif
inline string UTF8ToLocal(const string &strUTF8)
{
#if defined(_WIN32)
int nCodePage = GetConsoleOutputCP();
if (nCodePage == 936)
{
return UTF8ToGBK(strUTF8);
}
else
{
return strUTF8;
}
#else
return strUTF8;
#endif
}
#define PrintRsp(str) std::cout << str << endl;\
string strBody;\
ProtoBufToBodyData(stRsp, strBody);\
std::cout << strBody << endl;
#define Print(str) std::cout << str << endl;
#define PrintError(errMsg) std::cout << "ERROR: " << __FUNCTION__ << ", retMsg = " << errMsg << std::endl;
#define PrintUTF8(errMsg) std::cout << "ERROR: " << __FUNCTION__ << ", retMsg = " << UTF8ToLocal(errMsg) << std::endl;
inline void CPSleep(int32_t nSec)
{
#ifdef _WIN32
Sleep(nSec * 1000);
#else
struct timespec spec;
spec.tv_sec = nSec;
spec.tv_nsec = 0;
nanosleep(&spec, NULL);
#endif
}
class Semaphore
{
#if defined(_WIN32)
HANDLE m_sema;
#else
sem_t *m_sem;
#endif
public:
Semaphore(int32_t initValue)
{
#if defined(_WIN32)
m_sema = ::CreateSemaphoreA(NULL, initValue, 0x7fffffff, NULL);
#else
pid_t pid = getpid();
stringstream str;
str << "ftapi.sample." << (long)pid;
m_sem = ::sem_open(str.str().c_str(), O_CREAT | O_EXCL, S_IRWXU, initValue);
#endif
}
~Semaphore()
{
#if defined(_WIN32)
::CloseHandle(m_sema);
#else
::sem_close(m_sem);
#endif
}
void wait()
{
#if defined(_WIN32)
::WaitForSingleObject(m_sema, INFINITE);
#else
::sem_wait(m_sem);
#endif
}
void post()
{
#if defined(_WIN32)
::ReleaseSemaphore(m_sema, 1, NULL);
#else
::sem_post(m_sem);
#endif
}
bool trywait()
{
#if defined(_WIN32)
return WAIT_OBJECT_0 == ::WaitForSingleObject(m_sema, 0);
#else
return 0 == ::sem_trywait(m_sem);
#endif
}
};