#pragma once #ifdef _WIN32 #include #else #include #include #include #include #endif #include #include #include #include #include using namespace std; #include #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 } };