admin
2024-05-17 296ffe27dd5686e6897f414677b8164ec136e639
没有头文件的公共库添加
15个文件已添加
1753 ■■■■■ 已修改文件
common_nopch/ConfigUtil.cpp 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/ConfigUtil.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/JsonUtil.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/NetworkApi.cpp 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/NetworkApi.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/SocketManager.cpp 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/SocketManager.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/StringUtil.h 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/TimeUtil.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/WidgetsRenderUtil.cpp 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/WidgetsRenderUtil.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/Win32Util.cpp 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/Win32Util.h 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/md5.cpp 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/md5.h 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common_nopch/ConfigUtil.cpp
New file
@@ -0,0 +1,112 @@
#include "ConfigUtil.h"
#include "ConfigUtil.h"
#include <iostream>
#include <fstream>
bool fileExists(const std::string& filename) {
    std::ifstream file(filename);
    return file.good(); // 如果文件成功打开,则返回 true
}
void ConfigUtil::readConfig(libconfig::Config& config)
{
    string strConfPath = "config.cfg";
    if (!fileExists(strConfPath)) {
        std::ofstream file(strConfPath);
        file.is_open();
    }
    //解读配置文件
    try {
        config.readFile(strConfPath.c_str());
    }
    catch (const libconfig::FileIOException& fioex) {
        std::cerr << "I/O exception while reading the file." << std::endl;
    }
    catch (const libconfig::ParseException& pex) {
        std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
            << " - " << pex.getError() << std::endl;
    }
}
void ConfigUtil::writeConfig(libconfig::Config& config)
{
    config.writeFile("config.cfg");
}
int ConfigUtil::readIntConfig(const char* key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        int val;
        root.lookupValue(key, val);
        return val;
    }
    throw string("尚未获取到内容");
}
string ConfigUtil::readStringConfig(const char* key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        //string val;
        const char* val;
        root.lookupValue(key, val);
        return string(val);
    }
    throw string("尚未获取到内容");
}
void ConfigUtil::setIntConfig(const char* key, int val) {
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        root[key] = val;
    }
    else {
        root.add(key, libconfig::Setting::TypeInt) = val;
    }
    writeConfig(mConfig);
}
void ConfigUtil::setStringConfig(const char* key, string val) {
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        root[key] = val.c_str();
    }
    else {
        root.add(key, libconfig::Setting::TypeString) = val.c_str();
    }
    writeConfig(mConfig);
}
list<string> ConfigUtil::getKeys()
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    list<string> keys;
    for (auto iter = root.begin(); iter != root.end(); ++iter) {
        keys.push_back(iter->getName());
    }
    return keys;
}
void ConfigUtil::delKey(string key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    root.remove(key);
}
common_nopch/ConfigUtil.h
New file
@@ -0,0 +1,21 @@
#pragma once
#include<string>
#include <libconfig.h++>
#include<list>
using namespace std;
class ConfigUtil
{
private:
    static void readConfig(libconfig::Config& config);
    static void writeConfig(libconfig::Config& config);
protected:
    static int readIntConfig(const char* key);
    static string readStringConfig(const char* key);
    static void setIntConfig(const char* key, int val);
    static void setStringConfig(const char* key, string val);
    static list<string> getKeys();
    static void delKey(string key);
};
common_nopch/JsonUtil.h
New file
@@ -0,0 +1,37 @@
#pragma once
#include <string>
#include <list>
#include <set>
#include "StringUtil.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <rapidjson/prettywriter.h>
using namespace std;
class JsonUtil {
public:
    static  rapidjson::Document parseUTF8(string src) {
        rapidjson::Document root;
        root.Parse(src.c_str());
        return root;
    }
    static     rapidjson::GenericDocument<rapidjson::UTF16<>> parseUTF16(string src) {
        wstring wresult = StringUtil::Unescape(src);
        rapidjson::GenericDocument<rapidjson::UTF16<>> root;
        root.Parse(wresult.c_str());
        return root;
    }
    static string toJsonStr(rapidjson::Document& document) {
        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        document.Accept(writer);
        std::string jsonString = buffer.GetString();
        return jsonString;
    }
};
common_nopch/NetworkApi.cpp
New file
@@ -0,0 +1,154 @@
#include "NetworkApi.h"
#include <chrono>
#include <random>
#include "md5.h"
#include "SocketManager.h"
string NetworkApi::_TRADE_SERVER_ADDR ="43.138.167.68";
int NetworkApi::_TRADE_SERVER_PORT = 11008;
string NetworkApi::_COMMON_SERVER_ADDR;
int NetworkApi::_COMMON_SERVER_PORT;
string NetworkApi::get_rquest_id()
{
    string requestIdStr;
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    // 将当前时间点转换为time_t类型
    std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
    requestIdStr.append("_").append(std::to_string(currentTime)).append("_");
    // 生成随机数
    std::random_device rd;
    std::mt19937 rng(rd());
    std::uniform_int_distribution<int> intDist(1, 100000); // 生成范围在1-100之间的整数
    int randomInt = intDist(rng);
    requestIdStr.append(std::to_string(randomInt));
    return requestIdStr;
}
string NetworkApi::get_sign(rapidjson::Document& document)
{
    //计算签名
    std::list<string> strList;
    for (rapidjson::Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) {
        if (itr->value.IsObject() || itr->value.IsArray()) {
            //如果是对象
            rapidjson::StringBuffer buffer;
            rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
            itr->value.Accept(writer);
            std::string jsonString = buffer.GetString();
            strList.push_back(string(itr->name.GetString()).append("=").append(jsonString));
        }
        else {
            if (itr->value.IsString()) {
                strList.push_back(string(itr->name.GetString()).append("=").append(itr->value.GetString()));
            }
            else     if (itr->value.IsInt()) {
                strList.push_back(string(itr->name.GetString()).append("=").append(std::to_string(itr->value.GetInt())));
            }
        }
    }
    strList.sort();
    strList.push_back("%Yeshi2014@#.");
    string src = "";
    int index = 0;
    for (std::list<string>::iterator el = strList.begin(); el != strList.end(); el++) {
        src.append(*el);
        index++;
        if (index != strList.size()) {
            src.append("&");
        }
    }
    //MD5
    //cout << "加密前字符串:" <<src << endl;
    string md5 = MD5(src).toStr();
    return md5;
}
void NetworkApi::set_server_info(string trade_addr, int trade_port, string common_addr, int common_port)
{
    _TRADE_SERVER_ADDR = trade_addr;
    _TRADE_SERVER_PORT = trade_port;
    _COMMON_SERVER_ADDR = common_addr;
    _COMMON_SERVER_PORT = common_port;
}
std::string NetworkApi::load_request_data(std::string data)
{
    rapidjson::Document document;
    document.Parse(data.c_str());
    string requestIdStr = (document["type"].IsInt() ? std::to_string(document["type"].GetInt()) : document["type"].GetString()).append(get_rquest_id());
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
    // 添加 request_id 字段
    rapidjson::Value requestId(rapidjson::kStringType);
    requestId.SetString(requestIdStr.c_str(), allocator);
    document.AddMember("request_id", requestId, allocator);
    // 添加签名,sign
    string sign = get_sign(document);
    rapidjson::Value signV(rapidjson::kStringType);
    signV.SetString(sign.c_str(), allocator);
    document.AddMember("sign", signV, allocator);
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    document.Accept(writer);
    std::string jsonString = buffer.GetString();
    //发送数据
    std::stringstream ss;
    ss << std::setw(8) << std::setfill('0') << jsonString.length();
    std::string length_str = string("##").append(ss.str());
    std::string fstr = length_str.append(jsonString);
    return fstr;
}
//网络请求
std::string  NetworkApi::base_request(std::string data) {
    std::string fstr = load_request_data(data);
    try {
        return    SocketManager::sendMsg(_COMMON_SERVER_ADDR, _COMMON_SERVER_PORT, fstr.c_str());
    }
    catch (...) {
        throw L"网络请求出错";
    }
}
std::string NetworkApi::base_trade_request(std::string data)
{
    rapidjson::Document document;
    document.Parse(data.c_str());
    string requestIdStr = string(document["type"].GetString()).append(get_rquest_id());
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
    // 添加 request_id 字段
    rapidjson::Value requestId(rapidjson::kStringType);
    requestId.SetString(requestIdStr.c_str(), allocator);
    document.AddMember("request_id", requestId, allocator);
    // 添加签名,sign
    string sign = get_sign(document);
    rapidjson::Value signV(rapidjson::kStringType);
    signV.SetString(sign.c_str(), allocator);
    document.AddMember("sign", signV, allocator);
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    document.Accept(writer);
    std::string jsonString = buffer.GetString();
    //发送数据
    std::stringstream ss;
    ss << std::setw(8) << std::setfill('0') << jsonString.length();
    std::string length_str = string("##").append(ss.str());
    std::string fstr = length_str.append(jsonString);
    try {
        return    SocketManager::sendMsg(_TRADE_SERVER_ADDR, _TRADE_SERVER_PORT, fstr.c_str());
    }
    catch (...) {
        throw wstring(L"网络请求出错");
    }
}
common_nopch/NetworkApi.h
New file
@@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <list>
#include "JsonUtil.h"
using namespace std;
class NetworkApi
{
    protected:
        static  string _TRADE_SERVER_ADDR;
        static  int _TRADE_SERVER_PORT;
        static  string _COMMON_SERVER_ADDR;
        static  int _COMMON_SERVER_PORT;
        // 网络请求
        static std::string base_request(std::string data);
        // 请求交易服务器
        static std::string base_trade_request(std::string data);
        static string get_rquest_id();
        static string get_sign(rapidjson::Document& document);
public:
    static void set_server_info(string trade_addr,int trade_port, string common_addr,int common_port);
    static std::string load_request_data(std::string data);
};
common_nopch/SocketManager.cpp
New file
@@ -0,0 +1,131 @@
#include "SocketManager.h"
#include <string>
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
string SocketManager::ADDR;
SocketManager::~SocketManager() {
}
string SocketManager::sendMsg(const char* msg) {
    ADDR = "43.138.167.68";
    //ADDR = "192.168.3.122";
    return SocketManager::sendMsg(ADDR, PORT, msg);
}
string SocketManager::sendMsg(string addr, int port, const char* msg) {
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET m_SockClient;
    m_SockClient = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in clientaddr;
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_port = htons(port);
    //clientaddr.sin_addr.S_un.S_addr = ;
    inet_pton(AF_INET, addr.c_str(), &clientaddr.sin_addr);
    connect(m_SockClient, (sockaddr*)&clientaddr, sizeof(clientaddr));
    char buffer[1024];
    int result = send(m_SockClient, msg, strlen(msg), 0);
    if (result < 0) {
        throw string("发送失败");
    }
    int header_length = 10;
    int num = recv(m_SockClient, buffer, 1024, 0);
    string data = string(buffer, 0, num);
    if (data.find("##") == 0) {
        //带有头文件
        int count = std::stoi(data.substr(2, header_length - 2));
        data = data.substr(header_length);
        while (data.length() < count) {
            char buffer[1024];
            num = recv(m_SockClient, buffer, 1024, 0);
            if (num > 0) {
                data.append(string(buffer, 0, num));
            }
        }
    }
    closesocket(m_SockClient);
    if (num < 0) {
        throw string("未接收到信息");
    }
    return data;
}
string SocketManager::sendMsg(SOCKET m_SockClient, const char* msg)
{
    char buffer[1024];
    int result = send(m_SockClient, msg, strlen(msg), 0);
    if (result < 0) {
        throw string("发送失败");
    }
    int header_length = 10;
    int num = recv(m_SockClient, buffer, 1024, 0);
    string data = string(buffer, 0, num);
    if (data.find("##") == 0) {
        //带有头文件
        int count = std::stoi(data.substr(2, header_length - 2));
        data = data.substr(header_length);
        while (data.length() < count) {
            char buffer[1024];
            num = recv(m_SockClient, buffer, 1024, 0);
            if (num > 0) {
                data.append(string(buffer, 0, num));
            }
        }
    }
    if (num < 0) {
        throw string("未接收到信息");
    }
    return data;
}
SOCKET SocketManager::createSocket(string addr, int port)
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET m_SockClient;
    m_SockClient = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in clientaddr;
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_port = htons(port);
    //clientaddr.sin_addr.S_un.S_addr = ;
    inet_pton(AF_INET, addr.c_str(), &clientaddr.sin_addr);
    int c = connect(m_SockClient, (sockaddr*)&clientaddr, sizeof(clientaddr));
    if (c != 0) {
        throw string("socket连接失败");
    }
    return m_SockClient;
}
string SocketManager::receiveMsg(SOCKET m_SockClient)
{
    char buffer[1024];
    int header_length = 10;
    int num = recv(m_SockClient, buffer, 1024, 0);
    if (num <= 0) {
        throw string("连接已断开");
    }
    string data = string(buffer, 0, num);
    if (data.find("##") == 0) {
        //带有头文件
        int count = std::stoi(data.substr(2, header_length - 2));
        data = data.substr(header_length);
        while (data.length() < count) {
            char buffer[1024];
            num = recv(m_SockClient, buffer, 1024, 0);
            if (num > 0) {
                data.append(string(buffer, 0, num));
            }
        }
    }
    return data;
}
common_nopch/SocketManager.h
New file
@@ -0,0 +1,35 @@
#pragma once
#include<WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include <stdlib.h>
#include <list>
#include <iostream>
#include <atlstr.h>
// B类
#define MAIN_HOST "43.138.167.68"
#define API_PORT 11008
//A 类
//#define API_PORT 11009
using namespace std;
class SocketManager
{
private:
    static const int PORT = API_PORT;
    sockaddr_in clientaddr;
public:
    static string ADDR;
    static const int OCR_PORT = 9002;
    ~SocketManager();
    static string sendMsg(const char*);
    static string sendMsg(string addr, int port, const char*);
    static string sendMsg(SOCKET socket, const char*);
    static SOCKET createSocket(string addr = MAIN_HOST, int port = API_PORT);
    // 接收消息
    static string receiveMsg(SOCKET socket);
};
common_nopch/StringUtil.h
New file
@@ -0,0 +1,82 @@
#pragma once
#pragma once
#include <string>
#include <locale>
#include <codecvt>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
using namespace std;
class StringUtil {
public:
    static string wstringToString(wstring wt) {
        wstring_convert<codecvt_utf8<wchar_t>> conv;
        string result = conv.to_bytes(wt);
        return result;
    }
    static std::wstring Unescape(const std::string& input) {
        std::wstring wresult;
        for (size_t i = 0; i < input.length(); ) {
            if (input[i] == '\\' && input[i + 1] == 'u') {
                std::string code = input.substr(i + 2, 4);
                wchar_t unicode = stoi(code, nullptr, 16);
                wresult += unicode;
                i += 6;
            }
            else {
                wresult += input[i++];
            }
        }
        return wresult;
    }
    static string to_string(double val) {
        std::stringstream stream;
        stream << std::fixed << std::setprecision(2) << val;
        return stream.str();
    }
    static bool isNumber(const std::string& str) {
        if (str.empty()) {
            return false;
        }
        for (char c : str) {
            if (!isdigit(c)) {
                return false;
            }
        }
        return true;
    }
    // double转为字符串
    static string toString(double value, int precision) {
        std::ostringstream oss;
        oss << std::fixed << std::setprecision(precision) << value;
        return oss.str();
    }
    static std::vector<std::string> split(std::string str, std::string pattern) {
        std::string::size_type pos;
        std::vector<std::string> result;
        str += pattern;//扩展字符串以方便操作
        int size = str.size();
        for (int i = 0; i < size; i++)
        {
            pos = str.find(pattern, i);
            if (pos < size)
            {
                std::string s = str.substr(i, pos - i);
                result.push_back(s);
                i = pos + pattern.size() - 1;
            }
        }
        return result;
    }
};
common_nopch/TimeUtil.h
New file
@@ -0,0 +1,17 @@
#pragma once
#include <chrono>
class TimeUtil {
public:
    // 获取当前时间戳
    static UINT16 getNowTimeStamp() {
        auto now = std::chrono::system_clock::now();
        // 转换为时间戳
        auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
        // 获取时间戳值
        auto value = now_ms.time_since_epoch().count();
        return value;
    }
};
common_nopch/WidgetsRenderUtil.cpp
New file
@@ -0,0 +1,320 @@
#include "WidgetsRenderUtil.h"
#include <map>
using namespace std;
// 绘制内容信息
struct TextDrawInfo
{
    wxRect rect;//绘制的区域
    wxColour color;// 绘制的颜色
    wxString text;// 内容
};
// 行信息
struct LineInfo {
    int start_index;
    int end_index;
};
int WidgetsRenderUtil::drawText(wxDC* dc, wxString st, wxPoint startP, int lineWidth, int lineHeight, std::list<ColorIndexInfo> colors , wxColour defaultColor) {
    ///绘制可局部变色,可换行的富文本,返回高度
    /// 实现思路:1.先根据整体控件宽度或者换行符换行,确定行数
    /// 2.根据颜色的索引,确定绘制内容的文本,颜色,位置
    /// 3.根据第2步得到的数据,加上整个控件偏移量统一绘制文本内容
    // 计算是否需要换行
    wxString line_text;
    std::list<LineInfo> lines;
    int start_index = -1;
    for (int i = 0; i < st.length(); i++) {
        line_text.Append(st.GetChar(i));
        // 计算绘制文本占用的尺寸
        wxSize textSize = dc->GetTextExtent(line_text);
        if (start_index < 0 ) {
            start_index = i;
        }
        int nextCharWidth = 0;
        if (i + 1 < st.Length()) {
            // 获取下一个字符的长度
            wxSize textSize1 = dc->GetTextExtent(st.GetChar(i+1));
            nextCharWidth = textSize1.GetWidth();
        }
        if (textSize.GetWidth() + nextCharWidth > lineWidth) {
            lines.push_back(LineInfo({ start_index, i }));
            start_index = -1;
            line_text = "";
        }
        else if (st.GetChar(i) == '\n') {
            lines.push_back(LineInfo({ start_index, i }));
            start_index = -1;
            line_text = "";
        }
    }
    if (start_index >= 0) {
        lines.push_back(LineInfo({ start_index, (int)st.length() - 1 }));
        start_index = -1;
    }
    map<int, ColorIndexInfo> colorIndexMap;
    for (list<ColorIndexInfo>::iterator e = colors.begin(); e != colors.end(); ++e) {
        colorIndexMap[(*e).start_index] = *e;
        colorIndexMap[(*e).end_index] = *e;
    }
    list<TextDrawInfo> drawInfoList;
    int row = 0;
    wxColor color = defaultColor; // 默认颜色为黑色
    for (list<LineInfo>::iterator e = lines.begin(); e != lines.end(); ++e) {
        LineInfo lineInfo = *e;
        // 内容开始
        int content_start_index = -1;
        int positionLeft = 0;
        for (int i = lineInfo.start_index; i <= lineInfo.end_index; i++) {
            if (content_start_index < 0) {
                content_start_index = i;
            }
            // 绘制触发:一行结束,颜色开始,颜色结束
            if (colorIndexMap.find(i) != colorIndexMap.end()) {
                // 有颜色索引
                ColorIndexInfo info = colorIndexMap[i];
                if (info.start_index == i) {
                    // 颜色开始,将之前的数据加入绘制
                    if (i > content_start_index) {
                        TextDrawInfo drawInfo;
                        drawInfo.text = st.Mid(content_start_index, i - content_start_index);
                        drawInfo.color = color;
                        wxSize ts = dc->GetTextExtent(drawInfo.text);
                        drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                        drawInfoList.push_back(drawInfo);
                        // 起始点
                        content_start_index = i;
                        positionLeft += ts.GetWidth();
                    }
                    color = info.color;
                }
                if (info.end_index == i) {
                    //颜色结束
                    TextDrawInfo drawInfo;
                    drawInfo.text = st.Mid(content_start_index, i - content_start_index + 1);
                    drawInfo.color = color;
                    wxSize ts = dc->GetTextExtent(drawInfo.text);
                    drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                    drawInfoList.push_back(drawInfo);
                    // 起始点
                    content_start_index = -1;
                    positionLeft += ts.GetWidth();
                    //恢复默认颜色
                    color = defaultColor;
                }
            }
            if (i == lineInfo.end_index) {
                // 一行结束
                TextDrawInfo drawInfo;
                drawInfo.text = st.Mid(content_start_index, i - content_start_index + 1);
                drawInfo.color = color;
                wxSize ts = dc->GetTextExtent(drawInfo.text);
                drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                drawInfoList.push_back(drawInfo);
            }
        }
        row++;
    }
    for (list<TextDrawInfo>::iterator e = drawInfoList.begin(); e != drawInfoList.end(); ++e) {
        TextDrawInfo drawInfo = *e;
        dc->SetTextForeground(drawInfo.color);
        wxRect rect = drawInfo.rect;
        rect.x += startP.x;
        rect.y += startP.y;
        dc->DrawLabel(drawInfo.text, rect, wxALIGN_LEFT | wxALIGN_TOP);
    }
    return lines.size() * lineHeight;
}
int WidgetsRenderUtil::drawText(wxGraphicsContext* gc, wxString st, wxPoint startP, int lineWidth, int lineHeight, std::list<ColorIndexInfo> colors, wxColour defaultColor)
{
    ///绘制可局部变色,可换行的富文本,返回高度
/// 实现思路:1.先根据整体控件宽度或者换行符换行,确定行数
/// 2.根据颜色的索引,确定绘制内容的文本,颜色,位置
/// 3.根据第2步得到的数据,加上整个控件偏移量统一绘制文本内容
// 计算是否需要换行
    wxString line_text;
    std::list<LineInfo> lines;
    int start_index = -1;
    for (int i = 0; i < st.length(); i++) {
        line_text.Append(st.GetChar(i));
        // 计算绘制文本占用的尺寸
        wxDouble width, height;
        gc->GetTextExtent(line_text, &width,&height);
        wxSize textSize(width, height);
        if (start_index < 0) {
            start_index = i;
        }
        int nextCharWidth = 0;
        if (i + 1 < st.Length()) {
            // 获取下一个字符的长度
            wxDouble width, height;
            gc->GetTextExtent(st.GetChar(i + 1), &width, &height);
            wxSize textSize1(width, height);
            nextCharWidth = textSize1.GetWidth();
        }
        if (textSize.GetWidth() + nextCharWidth > lineWidth) {
            lines.push_back(LineInfo({ start_index, i }));
            start_index = -1;
            line_text = "";
        }
        else if (st.GetChar(i) == '\n') {
            lines.push_back(LineInfo({ start_index, i }));
            start_index = -1;
            line_text = "";
        }
    }
    if (start_index >= 0) {
        lines.push_back(LineInfo({ start_index, (int)st.length() - 1 }));
        start_index = -1;
    }
    map<int, ColorIndexInfo> colorIndexMap;
    for (list<ColorIndexInfo>::iterator e = colors.begin(); e != colors.end(); ++e) {
        colorIndexMap[(*e).start_index] = *e;
        colorIndexMap[(*e).end_index] = *e;
    }
    list<TextDrawInfo> drawInfoList;
    int row = 0;
    wxColor color = defaultColor; // 默认颜色为黑色
    for (list<LineInfo>::iterator e = lines.begin(); e != lines.end(); ++e) {
        LineInfo lineInfo = *e;
        // 内容开始
        int content_start_index = -1;
        int positionLeft = 0;
        for (int i = lineInfo.start_index; i <= lineInfo.end_index; i++) {
            if (content_start_index < 0) {
                content_start_index = i;
            }
            // 绘制触发:一行结束,颜色开始,颜色结束
            if (colorIndexMap.find(i) != colorIndexMap.end()) {
                // 有颜色索引
                ColorIndexInfo info = colorIndexMap[i];
                if (info.start_index == i) {
                    // 颜色开始,将之前的数据加入绘制
                    if (i > content_start_index) {
                        TextDrawInfo drawInfo;
                        drawInfo.text = st.Mid(content_start_index, i - content_start_index);
                        drawInfo.color = color;
                        wxDouble width, height;
                        gc->GetTextExtent(drawInfo.text, &width, &height);
                        wxSize ts(width, height);
                        drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                        drawInfoList.push_back(drawInfo);
                        // 起始点
                        content_start_index = i;
                        positionLeft += ts.GetWidth();
                    }
                    color = info.color;
                }
                if (info.end_index == i) {
                    //颜色结束
                    TextDrawInfo drawInfo;
                    drawInfo.text = st.Mid(content_start_index, i - content_start_index + 1);
                    drawInfo.color = color;
                    wxDouble width, height;
                    gc->GetTextExtent(drawInfo.text, &width, &height);
                    wxSize ts(width, height);
                    drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                    drawInfoList.push_back(drawInfo);
                    // 起始点
                    content_start_index = -1;
                    positionLeft += ts.GetWidth();
                    //恢复默认颜色
                    color = defaultColor;
                }
            }
            if (i == lineInfo.end_index) {
                // 一行结束
                TextDrawInfo drawInfo;
                drawInfo.text = st.Mid(content_start_index, i - content_start_index + 1);
                drawInfo.color = color;
                wxDouble width, height;
                gc->GetTextExtent(drawInfo.text, &width, &height);
                wxSize ts(width, height);
                drawInfo.rect = wxRect(positionLeft, row * lineHeight, ts.GetWidth(), lineHeight);
                drawInfoList.push_back(drawInfo);
            }
        }
        row++;
    }
    for (list<TextDrawInfo>::iterator e = drawInfoList.begin(); e != drawInfoList.end(); ++e) {
        TextDrawInfo drawInfo = *e;
        gc->SetPen(drawInfo.color);
        wxRect rect = drawInfo.rect;
        rect.x += startP.x;
        rect.y += startP.y;
        gc->DrawText(drawInfo.text, rect.x, rect.y);
    }
    return lines.size() * lineHeight;
    return 0;
}
void WidgetsRenderUtil::drawBtn(wxDC* dc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor)
{
    // 绘制按钮
    dc->SetPen(bgColor);
    dc->SetBrush(bgColor);
    dc->SetTextForeground(textColor);
    dc->DrawRectangle(rect);
    // 绘制按钮的文本
    dc->DrawLabel(st, rect, wxALIGN_CENTER);
}
void WidgetsRenderUtil::drawBtnByGC(wxGraphicsContext* gc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor)
{
    // 绘制按钮
    gc->SetPen(bgColor);
    gc->SetBrush(wxBrush(bgColor));
    gc->DrawRectangle(rect.x,rect.y,rect.width,rect.height);
    // 绘制按钮的文本
    wxDouble width, height;
    gc->GetTextExtent(st, &width, &height);
    gc->SetPen(textColor);
    gc->SetBrush(wxBrush(textColor));
    gc->DrawText(st, rect.x + (rect.width -  width)/2, rect.y + (rect.height - height) / 2);
}
common_nopch/WidgetsRenderUtil.h
New file
@@ -0,0 +1,35 @@
#pragma once
#include <wx/wx.h>
#include <wx/listctrl.h>
#include <wx/dataview.h>
#include <list>
#include <wx/graphics.h>
struct  ColorIndexInfo
{
    int start_index;
    int end_index;
    wxColour color;
};
class WidgetsRenderUtil {
public:
    // 绘制文本内容
    static int drawText(wxDC* dc, wxString st, wxPoint startP, int lineWidth, int lineHeight, std::list<ColorIndexInfo> colors = std::list<ColorIndexInfo>(), wxColour defaultColor = *wxBLACK);
    static int drawText(wxGraphicsContext* gc, wxString st, wxPoint startP, int lineWidth, int lineHeight, std::list<ColorIndexInfo> colors = std::list<ColorIndexInfo>(), wxColour defaultColor = *wxBLACK);
    // 绘制按钮
    static void drawBtn(wxDC* dc, wxString st, wxRect rect,wxColour textColor, wxColour bgColor);
    // 绘制按钮
    static void drawBtnByGC(wxGraphicsContext* gc, wxString st, wxRect rect, wxColour textColor, wxColour bgColor);
};
common_nopch/Win32Util.cpp
New file
@@ -0,0 +1,327 @@
#include "Win32Util.h"
#include <thread>
#include <vector>
#include "Win32Util.h"
void clickRunner(int delay) // 函数名字可随意
{
    Sleep(delay);
    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
    Sleep(10);
    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    Sleep(10);
}
void moveRunner(int x, int y, int delay) // 函数名字可随意
{
    Sleep(delay);
    SetCursorPos(x, y);
    Sleep(20);
}
void kbNumRunner(string nums, int delay) // 函数名字可随意
{
    Sleep(delay);
    for (int i = 0; i < nums.length(); i++)
    {
        int code = int(nums.c_str()[i]);
        if (code == '.')
        {
            code = 110;
        }
        keybd_event(code, 0, 0, 0);
        Sleep(5);
        keybd_event(code, 0, KEYEVENTF_KEYUP, 0);
        Sleep(20);
    }
}
void kbKeyRunner(int code, int delay) // 函数名字可随意
{
    Sleep(delay);
    keybd_event(code, 0, 0, 0);
    keybd_event(code, 0, KEYEVENTF_KEYUP, 0);
}
std::string  Win32Util::convertLPWSTRToUTF8(LPWSTR lpwstr) {
    int len = WideCharToMultiByte(CP_UTF8, 0, lpwstr, -1, NULL, 0, NULL, NULL);
    if (len == 0) {
        // 转换失败
        return "";
    }
    char* buffer = new char[len];
    WideCharToMultiByte(CP_UTF8, 0, lpwstr, -1, buffer, len, NULL, NULL);
    std::string result(buffer);
    delete[] buffer;
    return result;
}
list<HWND> Win32Util::searchWindow(string name) {
    auto hwnd = GetDesktopWindow();
    HWND mainPage = HWND();
    //获取桌面子窗口句柄
    hwnd = GetWindow(hwnd, GW_CHILD);
    list<HWND> list;
    while (hwnd != NULL)
    {
        std::string str = getWindowName(hwnd);
        if (str.find(name) != string::npos)
        {
            list.push_back(hwnd);
        }
        hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
    }
    return list;
}
string Win32Util::getWindowName(HWND hwnd) {
    int length = GetWindowTextLength(hwnd);
    TCHAR getbuf[10240];
    GetWindowText(hwnd, getbuf, length + 1);
    int iLen = WideCharToMultiByte(CP_ACP, 0, getbuf, -1, NULL, 0, NULL, NULL);   //首先计算TCHAR 长度。
    char* chRtn = (char*)alloca(iLen * sizeof(char));  //定义一个 TCHAR 长度大小的 CHAR 类型。
    WideCharToMultiByte(CP_ACP, 0, getbuf, -1, chRtn, iLen, NULL, NULL);  //将TCHAR 类型的数据转换为 CHAR 类型。
    std::string str(chRtn);
    return str;
}
string Win32Util::getClassName(HWND hwnd)
{
    TCHAR className[1024];
    GetClassName(hwnd, className, 1024);
    string st = convertLPWSTRToUTF8(className);
    return st;
}
wstring Win32Util::getText(HWND hwnd)
{
    int length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
    if (length == -1)
        return L"";
    wchar_t* buffer = new wchar_t[length + 1];
    SendMessage(hwnd, WM_GETTEXT, length + 1, (LPARAM)buffer);
    std::wstring str(buffer);
    delete[] buffer;
    return str;
}
void Win32Util::click(int delay) {
    thread clickRunner(clickRunner, delay);
    clickRunner.join();
}
void Win32Util::click(int x, int y, int delay) {
    thread clickRunner(moveRunner, x, y, delay);
    clickRunner.join();
    click();
}
void Win32Util::mouseMove(int x, int y, int delay) {
    thread clickRunner(moveRunner, x, y, delay);
    clickRunner.join();
}
void Win32Util::focus(HWND hwnd) {
    SetForegroundWindow(hwnd);
    SetFocus(hwnd);
}
//键盘输入数字
void Win32Util::keyboardNum(string num, int delay) {
    thread runner(kbNumRunner, num, delay);
    runner.join();
}
//键盘输入其他键
void Win32Util::keyboard(int code, int delay) {
    thread runner(kbKeyRunner, code, delay);
    runner.join();
}
void Win32Util::virtualKeyboard(HWND hwnd, int code)
{
    PostMessage(hwnd, WM_KEYDOWN, code, 0);
    PostMessage(hwnd, WM_KEYUP, code, 0);
}
void Win32Util::keyboardPaste()
{
    keybd_event(VK_CONTROL, 0, 0, 0);    // 按下CTRL键
    keybd_event('V', 0, 0, 0);    // 按下a键
    Sleep(50);
    keybd_event('V', 0, KEYEVENTF_KEYUP, 0);// 松开a键
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);// 松开CTRL键
}
DEVMODE Win32Util::getL2ScreenInfo()
{
    //获取屏幕数量
    DEVMODE dm;
    int screenNUm = GetSystemMetrics(SM_CMONITORS);
    for (int i = 0; i < screenNUm; i++) {
        DISPLAY_DEVICE device;
        ZeroMemory(&device, sizeof(DISPLAY_DEVICE));
        device.cb = sizeof(DISPLAY_DEVICE);
        EnumDisplayDevices(NULL, i, &device, NULL);
        ZeroMemory(&dm, sizeof(dm));
        dm.dmSize = sizeof(dm);
        EnumDisplaySettings(device.DeviceName, ENUM_CURRENT_SETTINGS, &dm);
        if (dm.dmPelsWidth > 3000) {
            return dm;
        }
    }
    throw string("尚未找到适合L2的显示设备");
    return DEVMODE();
}
void Win32Util::moveWin(HWND win, int x, int y, int width, int height) {
    MoveWindow(win, x, y, width, height, TRUE);
}
bool Win32Util::isWindowShow(HWND win) {
    return    IsWindowVisible(win);
}
void Win32Util::showWindow(HWND hwnd) {
    ShowWindow(hwnd, SW_SHOWNORMAL);
}
void Win32Util::rollMouseWheel(bool back, HWND win, int x, int y)
{
    //back-是否往后滚
    PostMessage(win, WM_MOUSEWHEEL, back ? 0xFF880000 : 0x00780000, MAKEWORD(x, y));
}
void Win32Util::getWindowRect(HWND hwnd, RECT* rect)
{
    GetWindowRect(hwnd, rect);
}
void Win32Util::visualClick(HWND hwnd, LPARAM pos)
{
    PostMessage(hwnd, WM_LBUTTONDOWN, 0x00000001, pos);
    PostMessage(hwnd, WM_LBUTTONUP, 0x00000000, pos);
}
string Win32Util::getNowTime()
{
    // 获取系统时间
    SYSTEMTIME sys;
    GetLocalTime(&sys);
    int h = sys.wHour;
    int m = sys.wMinute;
    int s = sys.wSecond;
    string st = "";
    if (h < 10) {
        st.append("0");
    }
    st.append(to_string(h));
    st.append(":");
    if (m < 10) {
        st.append("0");
    }
    st.append(to_string(m));
    st.append(":");
    if (s < 10) {
        st.append("0");
    }
    st.append(to_string(s));
    return st;
}
void Win32Util::sendMessage(HWND hwnd, UINT  msg, LPARAM p0, LPARAM p1)
{
    SendMessage(hwnd, msg, p0, p1);
}
void Win32Util::postMessage(HWND hwnd, UINT msg, LPARAM p0, LPARAM p1)
{
    PostMessage(hwnd, msg, p0, p1);
}
void Win32Util::input_num(HWND hwnd, string num_str)
{
    for (int i = 0; i < num_str.size(); i++)
    {
        SendMessage(hwnd, WM_KEYDOWN, num_str.c_str()[i], 0);
        PostMessage(hwnd, WM_KEYUP, num_str.c_str()[i], 0);
        Sleep(10);
    }
}
void Win32Util::addToTHS(string code)
{
    string leftCode = code.substr(1, 5);
    list<HWND> hwnds = searchWindow("看盘页面");
    HWND origin_hwnd = 0;
    for (list<HWND>::iterator e = hwnds.begin(); e != hwnds.end(); ++e) {
        HWND hwnd = *e;
        string name = Win32Util::getWindowName(hwnd);
        if (name.find("同花顺") >= 0) {
            origin_hwnd = hwnd;
        }
    }
    if (origin_hwnd <= 0) {
        throw  string("没有找到看盘页面");
        return;
    }
    input_num(origin_hwnd, code.substr(0, 1));
    Sleep(100);
    hwnds.clear();
    HWND topHwnd = GetDesktopWindow();
    HWND temp = 0;
    while (TRUE) {
        if (temp > 0 && isWindowShow(temp)) {
            string className = getClassName(temp);
            if (className.find("Afx:") == 0) {
                if (className.substr(className.length() - 2, 2).find( ":0")==0) {
                    hwnds.push_back(temp);
                    break;
                }
            }
        }
        temp = FindWindowEx(topHwnd, temp, NULL, NULL);
        if (temp <= 0) {
            break;
        }
    }
    if (hwnds.size() > 0)
    {
        HWND hwndroot = *(hwnds.begin());
        HWND hwnd = FindWindowEx(hwndroot, NULL, L"Edit", L"");
        input_num(hwnd, leftCode);
        Sleep(400);
        focus(hwndroot);
        SendMessage(hwndroot, WM_KEYDOWN, VK_RETURN, 0);
        Sleep(10);
        PostMessage(hwndroot, WM_KEYUP, VK_RETURN, 0);
    }
}
common_nopch/Win32Util.h
New file
@@ -0,0 +1,81 @@
#pragma once
#include <list>
#include <string>
#include <wtypes.h>
using namespace std;
class Win32Util
{
private:
    static    std::string convertLPWSTRToUTF8(LPWSTR lpwstr);
public:
    //按照名称搜索窗体
    static list<HWND> searchWindow(string name);
    //获取窗口名称
    static string getWindowName(HWND hwnd);
    static string getClassName(HWND hwnd);
    //获取获取控件内容
    static wstring getText(HWND hwnd);
    //单击
    static void click(int delay = 0);
    //单击指定位置
    static void click(int x, int y, int delay = 0);
    //移动鼠标
    static void mouseMove(int x, int y, int delay = 0);
    //获取焦点
    static void focus(HWND hwnd);
    //键盘输入数字
    static void keyboardNum(string num, int delay = 0);
    //键盘输入其他键
    static void keyboard(int code, int delay = 0);
    //虚拟键入
    static void virtualKeyboard(HWND hwnd, int code);
    //键盘键入粘贴
    static void keyboardPaste();
    //获取L2屏幕数据
    static DEVMODE getL2ScreenInfo();
    //移动窗口
    static void moveWin(HWND win, int x, int y, int width, int height);
    //窗体是否显示
    static bool isWindowShow(HWND hwnd);
    //显示窗口
    static void showWindow(HWND hwnd);
    //鼠标滚动
    static void rollMouseWheel(bool back, HWND win, int x, int y);
    //获取位置
    static void getWindowRect(HWND hwnd, RECT* rect);
    //虚拟点击
    static void visualClick(HWND hwnd, LPARAM pos);
    //获取现在的时间
    static string getNowTime();
    static void sendMessage(HWND hwnd, UINT  msg, LPARAM p0, LPARAM p1);
    static void postMessage(HWND hwnd, UINT  msg, LPARAM p0, LPARAM p1);
    static void input_num(HWND hwnd, string content);
    static  void addToTHS(string code);
};
common_nopch/md5.cpp
New file
@@ -0,0 +1,253 @@
#include "md5.h"
/* Define the static member of MD5. */
const byte MD5::PADDING[64] = { 0x80 };
const char MD5::HEX_NUMBERS[16] = {
        '0', '1', '2', '3',
        '4', '5', '6', '7',
        '8', '9', 'a', 'b',
        'c', 'd', 'e', 'f'
};
MD5::MD5(const string& message) {
    finished = false;
    /* Reset number of bits. */
    count[0] = count[1] = 0;
    /* Initialization constants. */
    state[0] = 0x67452301;
    state[1] = 0xefcdab89;
    state[2] = 0x98badcfe;
    state[3] = 0x10325476;
    /* Initialization the object according to message. */
    init((const byte*)message.c_str(), message.length());
}
/**
 * @Generate md5 digest.
 *
 * @return the message-digest.
 *
 */
const byte* MD5::getDigest() {
    if (!finished) {
        finished = true;
        byte bits[8];
        bit32 oldState[4];
        bit32 oldCount[2];
        bit32 index, padLen;
        /* Save current state and count. */
        memcpy(oldState, state, 16);
        memcpy(oldCount, count, 8);
        /* Save number of bits */
        encode(count, bits, 8);
        /* Pad out to 56 mod 64. */
        index = (bit32)((count[0] >> 3) & 0x3f);
        padLen = (index < 56) ? (56 - index) : (120 - index);
        init(PADDING, padLen);
        /* Append length (before padding) */
        init(bits, 8);
        /* Store state in digest */
        encode(state, digest, 16);
        /* Restore current state and count. */
        memcpy(state, oldState, 16);
        memcpy(count, oldCount, 8);
    }
    return digest;
}
/**
 * @Initialization the md5 object, processing another message block,
 * and updating the context.
 *
 * @param {input} the input message.
 *
 * @param {len} the number btye of message.
 *
 */
void MD5::init(const byte* input, size_t len) {
    bit32 i, index, partLen;
    finished = false;
    /* Compute number of bytes mod 64 */
    index = (bit32)((count[0] >> 3) & 0x3f);
    /* update number of bits */
    if ((count[0] += ((bit32)len << 3)) < ((bit32)len << 3)) {
        ++count[1];
    }
    count[1] += ((bit32)len >> 29);
    partLen = 64 - index;
    /* transform as many times as possible. */
    if (len >= partLen) {
        memcpy(&buffer[index], input, partLen);
        transform(buffer);
        for (i = partLen; i + 63 < len; i += 64) {
            transform(&input[i]);
        }
        index = 0;
    }
    else {
        i = 0;
    }
    /* Buffer remaining input */
    memcpy(&buffer[index], &input[i], len - i);
}
void MD5::transform(const byte block[64]) {
    bit32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    decode(block, x, 64);
    /* Round 1 */
    FF(a, b, c, d, x[0], s11, 0xd76aa478);
    FF(d, a, b, c, x[1], s12, 0xe8c7b756);
    FF(c, d, a, b, x[2], s13, 0x242070db);
    FF(b, c, d, a, x[3], s14, 0xc1bdceee);
    FF(a, b, c, d, x[4], s11, 0xf57c0faf);
    FF(d, a, b, c, x[5], s12, 0x4787c62a);
    FF(c, d, a, b, x[6], s13, 0xa8304613);
    FF(b, c, d, a, x[7], s14, 0xfd469501);
    FF(a, b, c, d, x[8], s11, 0x698098d8);
    FF(d, a, b, c, x[9], s12, 0x8b44f7af);
    FF(c, d, a, b, x[10], s13, 0xffff5bb1);
    FF(b, c, d, a, x[11], s14, 0x895cd7be);
    FF(a, b, c, d, x[12], s11, 0x6b901122);
    FF(d, a, b, c, x[13], s12, 0xfd987193);
    FF(c, d, a, b, x[14], s13, 0xa679438e);
    FF(b, c, d, a, x[15], s14, 0x49b40821);
    /* Round 2 */
    GG(a, b, c, d, x[1], s21, 0xf61e2562);
    GG(d, a, b, c, x[6], s22, 0xc040b340);
    GG(c, d, a, b, x[11], s23, 0x265e5a51);
    GG(b, c, d, a, x[0], s24, 0xe9b6c7aa);
    GG(a, b, c, d, x[5], s21, 0xd62f105d);
    GG(d, a, b, c, x[10], s22, 0x2441453);
    GG(c, d, a, b, x[15], s23, 0xd8a1e681);
    GG(b, c, d, a, x[4], s24, 0xe7d3fbc8);
    GG(a, b, c, d, x[9], s21, 0x21e1cde6);
    GG(d, a, b, c, x[14], s22, 0xc33707d6);
    GG(c, d, a, b, x[3], s23, 0xf4d50d87);
    GG(b, c, d, a, x[8], s24, 0x455a14ed);
    GG(a, b, c, d, x[13], s21, 0xa9e3e905);
    GG(d, a, b, c, x[2], s22, 0xfcefa3f8);
    GG(c, d, a, b, x[7], s23, 0x676f02d9);
    GG(b, c, d, a, x[12], s24, 0x8d2a4c8a);
    /* Round 3 */
    HH(a, b, c, d, x[5], s31, 0xfffa3942);
    HH(d, a, b, c, x[8], s32, 0x8771f681);
    HH(c, d, a, b, x[11], s33, 0x6d9d6122);
    HH(b, c, d, a, x[14], s34, 0xfde5380c);
    HH(a, b, c, d, x[1], s31, 0xa4beea44);
    HH(d, a, b, c, x[4], s32, 0x4bdecfa9);
    HH(c, d, a, b, x[7], s33, 0xf6bb4b60);
    HH(b, c, d, a, x[10], s34, 0xbebfbc70);
    HH(a, b, c, d, x[13], s31, 0x289b7ec6);
    HH(d, a, b, c, x[0], s32, 0xeaa127fa);
    HH(c, d, a, b, x[3], s33, 0xd4ef3085);
    HH(b, c, d, a, x[6], s34, 0x4881d05);
    HH(a, b, c, d, x[9], s31, 0xd9d4d039);
    HH(d, a, b, c, x[12], s32, 0xe6db99e5);
    HH(c, d, a, b, x[15], s33, 0x1fa27cf8);
    HH(b, c, d, a, x[2], s34, 0xc4ac5665);
    /* Round 4 */
    II(a, b, c, d, x[0], s41, 0xf4292244);
    II(d, a, b, c, x[7], s42, 0x432aff97);
    II(c, d, a, b, x[14], s43, 0xab9423a7);
    II(b, c, d, a, x[5], s44, 0xfc93a039);
    II(a, b, c, d, x[12], s41, 0x655b59c3);
    II(d, a, b, c, x[3], s42, 0x8f0ccc92);
    II(c, d, a, b, x[10], s43, 0xffeff47d);
    II(b, c, d, a, x[1], s44, 0x85845dd1);
    II(a, b, c, d, x[8], s41, 0x6fa87e4f);
    II(d, a, b, c, x[15], s42, 0xfe2ce6e0);
    II(c, d, a, b, x[6], s43, 0xa3014314);
    II(b, c, d, a, x[13], s44, 0x4e0811a1);
    II(a, b, c, d, x[4], s41, 0xf7537e82);
    II(d, a, b, c, x[11], s42, 0xbd3af235);
    II(c, d, a, b, x[2], s43, 0x2ad7d2bb);
    II(b, c, d, a, x[9], s44, 0xeb86d391);
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
}
/**
* @Encodes input (unsigned long) into output (byte).
*
* @param {input} usigned long.
*
* @param {output} byte.
*
* @param {length} the length of input.
*
*/
void MD5::encode(const bit32* input, byte* output, size_t length) {
    for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
        output[j] = (byte)(input[i] & 0xff);
        output[j + 1] = (byte)((input[i] >> 8) & 0xff);
        output[j + 2] = (byte)((input[i] >> 16) & 0xff);
        output[j + 3] = (byte)((input[i] >> 24) & 0xff);
    }
}
/**
 * @Decodes input (byte) into output (usigned long).
 *
 * @param {input} bytes.
 *
 * @param {output} unsigned long.
 *
 * @param {length} the length of input.
 *
 */
void MD5::decode(const byte* input, bit32* output, size_t length) {
    for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
        output[i] = ((bit32)input[j]) | (((bit32)input[j + 1]) << 8) |
            (((bit32)input[j + 2]) << 16) | (((bit32)input[j + 3]) << 24);
    }
}
/**
 * @Convert digest to string value.
 *
 * @return the hex string of digest.
 *
 */
string MD5::toStr() {
    const byte* digest_ = getDigest();
    string str;
    str.reserve(16 << 1);
    for (size_t i = 0; i < 16; ++i) {
        int t = digest_[i];
        int a = t / 16;
        int b = t % 16;
        str.append(1, HEX_NUMBERS[a]);
        str.append(1, HEX_NUMBERS[b]);
    }
    return str;
}
common_nopch/md5.h
New file
@@ -0,0 +1,118 @@
#pragma once
//
// Created by Admin on 2022/9/24.
//
#ifndef CODEMD5_MD5_H
#define CODEMD5_MD5_H
/* Parameters of MD5. */
#define s11 7
#define s12 12
#define s13 17
#define s14 22
#define s21 5
#define s22 9
#define s23 14
#define s24 20
#define s31 4
#define s32 11
#define s33 16
#define s34 23
#define s41 6
#define s42 10
#define s43 15
#define s44 21
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
#define ROTATELEFT(num, n) (((num) << (n)) | ((num) >> (32-(n))))
#define FF(a, b, c, d, x, s, ac) { \
  (a) += F ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
  (a) += G ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
  (a) += H ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
  (a) += I ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#include <string>
#include <cstring>
using std::string;
/* Define of btye.*/
typedef unsigned char byte;
/* Define of byte. */
typedef unsigned int bit32;
class MD5 {
public:
    /* Construct a MD5 object with a string. */
    MD5(const string& message);
    /* Generate md5 digest. */
    const byte* getDigest();
    /* Convert digest to string value */
    string toStr();
private:
    /* Initialization the md5 object, processing another message block,
     * and updating the context.*/
    void init(const byte* input, size_t len);
    /* MD5 basic transformation. Transforms state based on block. */
    void transform(const byte block[64]);
    /* Encodes input (usigned long) into output (byte). */
    void encode(const bit32* input, byte* output, size_t length);
    /* Decodes input (byte) into output (usigned long). */
    void decode(const byte* input, bit32* output, size_t length);
private:
    /* Flag for mark whether calculate finished. */
    bool finished;
    /* state (ABCD). */
    bit32 state[4];
    /* number of bits, low-order word first. */
    bit32 count[2];
    /* input buffer. */
    byte buffer[64];
    /* message digest. */
    byte digest[16];
    /* padding for calculate. */
    static const byte PADDING[64];
    /* Hex numbers. */
    static const char HEX_NUMBERS[16];
};
#endif //CODEMD5_MD5_H