mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-02 20:08:21 +08:00
commit
6e8c263024
@ -2,6 +2,13 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define chdir _chdir
|
||||
#define getcwd _getcwd
|
||||
#endif // MSVC
|
||||
|
||||
static void create_files(const std::vector<std::string>& files)
|
||||
{
|
||||
|
@ -12,4 +12,3 @@
|
||||
|
||||
#include "lib_acl.h"
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
#include "lib_protocol.h"
|
||||
|
@ -43,6 +43,14 @@ public:
|
||||
*/
|
||||
query& set_parameter(const char* name, const char *value);
|
||||
|
||||
/**
|
||||
* 设置字符串类型的变量值
|
||||
* @param name {const char*} 变量名
|
||||
* @param value {const char*} 变量值
|
||||
* @return {query&}
|
||||
*/
|
||||
query& set_parameter(const char* name, const std::string &value);
|
||||
|
||||
/**
|
||||
* 设置字符类型的变量值
|
||||
* @param name {const char*} 变量名
|
||||
|
@ -100,7 +100,7 @@ public:
|
||||
* @return {bool} 返回处理结果,返回 false 表示处理失败或处理成功且不保持
|
||||
* 长连接,应关闭连接
|
||||
*/
|
||||
bool doRun();
|
||||
virtual bool doRun();
|
||||
|
||||
/**
|
||||
* HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数
|
||||
@ -111,7 +111,7 @@ public:
|
||||
* 的关闭情况,这样可以方便与 acl_master 架构结合
|
||||
* @return {bool} 返回处理结果
|
||||
*/
|
||||
bool doRun(session& session, socket_stream* stream = NULL);
|
||||
virtual bool doRun(session& session, socket_stream* stream = NULL);
|
||||
|
||||
/**
|
||||
* HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数,
|
||||
@ -120,7 +120,7 @@ public:
|
||||
* @param stream {socket_stream*} 含义同上
|
||||
* @return {bool} 返回处理结果
|
||||
*/
|
||||
bool doRun(const char* memcached_addr, socket_stream* stream);
|
||||
virtual bool doRun(const char* memcached_addr, socket_stream* stream);
|
||||
|
||||
/**
|
||||
* 当 HTTP 请求为 GET 方式时调用的虚函数
|
||||
|
156
lib_acl_cpp/include/acl_cpp/http/WebSocketServlet.hpp
Normal file
156
lib_acl_cpp/include/acl_cpp/http/WebSocketServlet.hpp
Normal file
@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
#include "stdlib/acl_mymalloc.h"
|
||||
#include "HttpServlet.hpp"
|
||||
#include "websocket.hpp"
|
||||
|
||||
namespace acl
|
||||
{
|
||||
class WebSocketServlet: public HttpServlet
|
||||
{
|
||||
public:
|
||||
WebSocketServlet();
|
||||
/**
|
||||
* 构造函数
|
||||
* @param stream {socket_stream*} 当在 acl_master 服务器框架控制下
|
||||
* 运行时,该参数必须非空;当在 apache 下以 CGI 方式运行时,该参数
|
||||
* 设为 NULL;另外,该函数内部不会关闭流连接,应用应自行处理流对象
|
||||
* 的关闭情况,这样可以方便与 acl_master 架构结合
|
||||
* @param session {session*} 每一个 HttpServlet 对象一个 session 对象
|
||||
*/
|
||||
WebSocketServlet(socket_stream* stream, session* session);
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param stream {socket_stream*} 当在 acl_master 服务器框架控制下
|
||||
* 运行时,该参数必须非空;当在 apache 下以 CGI 方式运行时,该参数
|
||||
* 设为 NULL;另外,该函数内部不会关闭流连接,应用应自行处理流对象
|
||||
* 的关闭情况,这样可以方便与 acl_master 架构结合
|
||||
* @param memcache_addr {const char*}
|
||||
*/
|
||||
WebSocketServlet(socket_stream* stream, const char* memcache_addr = "127.0.0.1:11211");
|
||||
|
||||
/**
|
||||
* HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数,
|
||||
* 该函数首先会调用 start 过程,然后根据 start 的返回结果及请求/响应
|
||||
* 对象是否要求保持长连接来决定是否需要与客户端保持长连接.
|
||||
* @return {bool} 返回处理结果,返回 false 表示处理失败或处理成功且不保持
|
||||
* 长连接,应关闭连接
|
||||
*/
|
||||
|
||||
virtual ~WebSocketServlet();
|
||||
|
||||
/**
|
||||
* HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数
|
||||
* @param session {session&} 存储 session 数据的对象
|
||||
* @param stream {socket_stream*} 当在 acl_master 服务器框架控制下
|
||||
* 运行时,该参数必须非空;当在 apache 下以 CGI 方式运行时,该参数
|
||||
* 设为 NULL;另外,该函数内部不会关闭流连接,应用应自行处理流对象
|
||||
* 的关闭情况,这样可以方便与 acl_master 架构结合
|
||||
* @return {bool} 返回处理结果
|
||||
*/
|
||||
virtual bool doRun(session& session, socket_stream* stream = NULL)
|
||||
{
|
||||
return HttpServlet::doRun(session, stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数,
|
||||
* 调用本函数意味着采用 memcached 来存储 session 数据
|
||||
* @param memcached_addr {const char*} memcached 服务器地址,格式:IP:PORT
|
||||
* @param stream {socket_stream*} 含义同上
|
||||
* @return {bool} 返回处理结果
|
||||
*/
|
||||
virtual bool doRun(const char* memcached_addr, socket_stream* stream)
|
||||
{
|
||||
return HttpServlet::doRun(memcached_addr, stream);
|
||||
}
|
||||
|
||||
virtual bool doRun();
|
||||
/**
|
||||
* 发送二进制数据.
|
||||
* @param rw_timeout {const char *} 发送的数据
|
||||
* @return {bool} 错误 false.否则 true
|
||||
*/
|
||||
|
||||
bool send_binary(const char *buf, int len);
|
||||
|
||||
|
||||
/**
|
||||
* 发送文本数据.
|
||||
* @param rw_timeout {const char *} 发送的数据
|
||||
* @return {bool} 错误 false.否则 true
|
||||
*/
|
||||
|
||||
bool send_text(const char *text);
|
||||
|
||||
|
||||
/**
|
||||
* 发送pong 消息.
|
||||
* @param rw_timeout {const char *} 发送的数据
|
||||
* @return {bool} 错误 false.否则 true
|
||||
*/
|
||||
bool send_pong(const char *buffer = NULL);
|
||||
|
||||
/**
|
||||
* 发送pong 消息.
|
||||
* @param rw_timeout {const char *} 发送的数据
|
||||
* @return {bool} 错误 false.否则 true
|
||||
*/
|
||||
bool send_ping(const char *buffer = NULL);
|
||||
|
||||
unsigned long long get_max_msg_len()
|
||||
{
|
||||
return max_msg_len_;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最大消息长度,当websocket 消息大于这个值,将断开websocket连接.
|
||||
* @param unsigned long long{len} 新的长度
|
||||
*/
|
||||
void set_max_msg_len(unsigned long long len)
|
||||
{
|
||||
max_msg_len_ = len;
|
||||
}
|
||||
protected:
|
||||
|
||||
/**
|
||||
* websocket 关闭消息回调
|
||||
* @return {void}
|
||||
*/
|
||||
virtual void on_close();
|
||||
/**
|
||||
* websocket ping 消息回调.
|
||||
* @param {const char *} buf 消息数据
|
||||
* @param {int} len 消息数据长度
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_ping(const char *buf, unsigned long long len) = 0;
|
||||
/**
|
||||
* websocket pong 消息回调.
|
||||
* @param {const char *} buf 消息数据
|
||||
* @param {int} len 消息数据长度
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_pong(const char *buf, unsigned long long len) = 0;
|
||||
|
||||
/**
|
||||
* websocket ping 消息回调.
|
||||
* @param data{char *} 回调数据缓存区。
|
||||
* @param len{unsigned long long}回调数据缓存区长度。
|
||||
* @param text{bool } true 为文本数据。否则是 二进制数据。
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_message(char *data, unsigned long long len, bool text) = 0;
|
||||
|
||||
private:
|
||||
bool doWebsocket(HttpServletRequest&, HttpServletResponse&);
|
||||
private:
|
||||
|
||||
unsigned long long max_msg_len_;
|
||||
websocket *ws_;
|
||||
|
||||
char *recv_buffer_;
|
||||
int write_pos_;
|
||||
int opcode_;
|
||||
};
|
||||
}
|
@ -118,6 +118,7 @@ private:
|
||||
|
||||
bool check_namespace();
|
||||
bool check_namespace_end();
|
||||
bool check_using_namespace();
|
||||
bool check_struct_begin ();
|
||||
bool check_struct_end ();
|
||||
bool check_include();
|
||||
|
14
lib_acl_cpp/samples/http/webSocketServlet/Makefile
Normal file
14
lib_acl_cpp/samples/http/webSocketServlet/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
base_path = ../../..
|
||||
PROG = WebSocketServlet
|
||||
include ../../Makefile.in
|
||||
#Path for SunOS
|
||||
ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS)
|
||||
EXTLIBS = -liconv
|
||||
endif
|
||||
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
|
||||
EXTLIBS = -L/usr/local/lib -liconv
|
||||
endif
|
||||
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
|
||||
EXTLIBS += -L/usr/lib -liconv
|
||||
endif
|
||||
EXTLIBS += -lz
|
135
lib_acl_cpp/samples/http/webSocketServlet/WebSocketServlet.cf
Normal file
135
lib_acl_cpp/samples/http/webSocketServlet/WebSocketServlet.cf
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
service http_server {
|
||||
# 进程是否禁止运行
|
||||
master_disable = no
|
||||
# 服务地址及端口号
|
||||
# for master_type = inet
|
||||
# master_service = 127.0.0.1:5001
|
||||
# for master_type = unix
|
||||
# master_service = echo.sock
|
||||
# for master_type = sock
|
||||
master_service = 127.0.0.1:5001, 5002, :5003, echo.sock, echo2.sock
|
||||
|
||||
# 服务监听为域套接口
|
||||
# master_service = aio_echo.sock
|
||||
# 服务类型
|
||||
# master_type = inet
|
||||
# master_type = unix
|
||||
master_type = sock
|
||||
|
||||
# 当子进程异常退出时,如果该值非空,则将子进程异常退出的消息通知该服务
|
||||
# master_notify_addr = 127.0.0.1:5801
|
||||
# 邮件通知接收者
|
||||
# master_notify_recipients = zhengshuxin@hotmail.com
|
||||
|
||||
# 是否允许延迟接受客户端连接,如果为0则表示关闭该功能,如果大于0则表示打开此功能
|
||||
# 并且此值代表延迟接受连接的超时值,超过此值时如果客户端依然没有发来数据,则操作
|
||||
# 系统会在系统层直接关闭该连接
|
||||
# master_defer_accept = 0
|
||||
# 是否只允许私有访问, 如果为 y, 则域套接口创建在 {install_path}/var/log/private/ 目录下,
|
||||
# 如果为 n, 则域套接口创建在 {install_path}/var/log/public/ 目录下,
|
||||
master_private = n
|
||||
master_unpriv = n
|
||||
# 是否需要 chroot: n -- no, y -- yes
|
||||
master_chroot = n
|
||||
# 每隔多长时间触发一次,单位为秒(仅对 trigger 模式有效)
|
||||
master_wakeup = -
|
||||
# 最大进程数
|
||||
master_maxproc = 1
|
||||
# 预启动进程数,该值不得大于 master_maxproc
|
||||
# master_prefork = 0
|
||||
# 进程程序名
|
||||
master_command = WebSocketServlet
|
||||
# 进程日志记录文件
|
||||
master_log = {install_path}/var/log/http_server
|
||||
# 调试日志方式,格式:tag:level; tag:level; tab:level, 如:all:1; 101:2
|
||||
# master_debug =
|
||||
# 进程启动参数,只能为: -u [是否允许以某普通用户的身份运行]
|
||||
# master_args =
|
||||
# 传递给服务子进程的环境变量, 可以通过 getenv("SERVICE_ENV") 获得此值
|
||||
# master_env = mempool_limit:512000000
|
||||
# master_env = logme:FALSE, priority:E_LOG_INFO, action:E_LOG_PER_DAY, flush:sync_flush, imit_size:512,\
|
||||
# sync_action:E_LOG_SEM, sem_name:/tmp/ioctl_echo.sem
|
||||
|
||||
# 当启动多个子进程实例时,该开关控制多个子进程在接收连接时是否向 acl_master 发送消息报告自己的状态
|
||||
# master_status_notify = 1
|
||||
# 是否允许产生 core 文件
|
||||
# ioctl_enable_core = 1
|
||||
# 每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出
|
||||
ioctl_use_limit = 100
|
||||
# 每个进程实例的空闲超时时间,超过此值后进程实例主动退出
|
||||
ioctl_idle_limit = 120
|
||||
# 记录进程PID的位置(对于多进程实例来说没有意义)
|
||||
ioctl_pid_dir = {install_path}/var/pid
|
||||
# 进程运行时所在的路径
|
||||
ioctl_queue_dir = {install_path}/var
|
||||
# 读写超时时间, 单位为秒
|
||||
ioctl_rw_timeout = 120
|
||||
# 读缓冲区的缓冲区大小
|
||||
ioctl_buf_size = 8192
|
||||
# 每次 accept 时的循环接收的最大次数
|
||||
ioctl_max_accept = 25
|
||||
# 在并发访问量非常低的情况下,如访问量在 10 次/秒 以下时,可以找开此值(即赋为1),
|
||||
# 以加速事件循环过程, 从而防止服务进程阻塞在 select 上的时间过长而影响访问速度
|
||||
# ioctl_enable_dog = 1
|
||||
# 进程运行时的用户身份
|
||||
ioctl_owner = root
|
||||
|
||||
# 用 select 进行循环时的时间间隔
|
||||
# 单位为秒
|
||||
ioctl_delay_sec = 1
|
||||
# 单位为微秒
|
||||
ioctl_delay_usec = 500
|
||||
|
||||
# 采用事件循环的方式: select(default), poll, kernel(epoll/devpoll/kqueue)
|
||||
ioctl_event_mode = kernel
|
||||
# 事件引擎检查所有空闲描述符的时间间隔(毫秒)
|
||||
# ioctl_check_inter = 100
|
||||
# 当启用 master_dispatch 连接分开服务后,该配置指定 master_dispatch 所监听的
|
||||
# 域套接口的全路径,这样本子进程就可以从 master_dispatch 获得客户端连接
|
||||
# ioctl_dispatch_addr = {install_path}/var/private/dispatch.sock
|
||||
# 当 ioctl_dispatch_addr 开启后,下面参数控制本服务进程发给前端 master_dispatch 的服务标识信息
|
||||
# ioctl_dispatch_type = default
|
||||
|
||||
# 线程池的最大线程数
|
||||
ioctl_max_threads = 250
|
||||
# 线程池中工作线程等待任务时间间隔(毫秒)
|
||||
# ioctl_schedule_wait = 50
|
||||
# 线程任务调度的时间间隔大于此值(毫秒)后记警告日志
|
||||
# ioctl_schedule_warn = 100
|
||||
# 线程处理任务拥堵数超过此阀值后记警告日志,设为 0 则内部只有当拥堵任务数超过总线程数的 10 倍时才报警
|
||||
# ioctl_qlen_warn = 0
|
||||
# 线程的堆栈空间大小,单位为字节,0表示使用系统缺省值
|
||||
ioctl_stacksize = 0
|
||||
# 允许访问 udserver 的客户端IP地址范围
|
||||
ioctl_access_allow = 127.0.0.1:255.255.255.255, 127.0.0.1:127.0.0.1
|
||||
|
||||
# 当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出
|
||||
ioctl_quick_abort = 1
|
||||
|
||||
############################################################################
|
||||
# 应用自己的配置选项
|
||||
|
||||
# mysql 服务地址
|
||||
# mysql_dbaddr = /tmp/mysql.sock
|
||||
# mysql_dbaddr = 10.0.250.199:3306
|
||||
# 连接 mysql 数据库的连接池的最大值
|
||||
# mysql_dbmax = 200
|
||||
# ping mysql 连接的间隔时间, 以秒为单位
|
||||
# mysql_dbping = 10
|
||||
# mysql 连接空闲的时间间隔, 以秒为单位
|
||||
# mysql_dbtimeout = 30
|
||||
|
||||
# 数据库名称
|
||||
# mysql_dbname = ioctl_db
|
||||
# 数据库访问用户
|
||||
# mysql_dbuser = ioctl_user
|
||||
# 数据库用户访问密码
|
||||
# mysql_dbpass = 111111
|
||||
|
||||
# 是否输出当前内存的状态信息
|
||||
# debug_mem = 1
|
||||
# 是否在一个线程中连接读
|
||||
# loop_read = 1
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
#include "stdafx.h"
|
||||
#include "WebsocketServlet_impl.h"
|
||||
|
||||
WebsocketServlet_impl::WebsocketServlet_impl(acl::redis_client_cluster& cluster, size_t max_conns)
|
||||
{
|
||||
// 创建 session 存储对象
|
||||
session_ = new acl::redis_session(cluster, max_conns);
|
||||
step_ = 0;
|
||||
}
|
||||
|
||||
WebsocketServlet_impl::~WebsocketServlet_impl(void)
|
||||
{
|
||||
delete session_;
|
||||
}
|
||||
|
||||
bool WebsocketServlet_impl::doUnknown(acl::HttpServletRequest&,
|
||||
acl::HttpServletResponse& res)
|
||||
{
|
||||
res.setStatus(400);
|
||||
res.setContentType("text/html; charset=");
|
||||
// 发送 http 响应头
|
||||
if (res.sendHeader() == false)
|
||||
return false;
|
||||
// 发送 http 响应体
|
||||
acl::string buf("<root error='unkown request method' />\r\n");
|
||||
(void) res.getOutputStream().write(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebsocketServlet_impl::doGet(acl::HttpServletRequest& req,
|
||||
acl::HttpServletResponse& res)
|
||||
{
|
||||
return doPost(req, res);
|
||||
}
|
||||
|
||||
bool WebsocketServlet_impl::doPost(acl::HttpServletRequest& req,
|
||||
acl::HttpServletResponse& res)
|
||||
{
|
||||
res.setContentType("text/html; charset=utf-8") // 设置响应字符集
|
||||
.setContentEncoding(false) // 设置是否压缩数据
|
||||
.setChunkedTransferEncoding(true); // 采用 chunk 传输方式
|
||||
|
||||
const char* ip = req.getLocalAddr();
|
||||
if (ip == NULL || *ip == 0)
|
||||
{
|
||||
logger_error("getLocalAddr error");
|
||||
return false;
|
||||
}
|
||||
unsigned short port = req.getLocalPort();
|
||||
if (port == 0)
|
||||
{
|
||||
logger_error("getLocalPort error");
|
||||
return false;
|
||||
}
|
||||
|
||||
acl::string local_addr;
|
||||
local_addr << ip << ":" << port;
|
||||
|
||||
printf("getLocalAddr: %s\r\n", local_addr.c_str());
|
||||
|
||||
acl::string html_file;
|
||||
html_file << "www/upload.html";
|
||||
acl::string buf;
|
||||
if (acl::ifstream::load(html_file, &buf) == false)
|
||||
{
|
||||
logger_error("load %s error %s",
|
||||
html_file.c_str(), acl::last_serror());
|
||||
return doError(req, res);
|
||||
}
|
||||
|
||||
buf << "<script>g_url='ws://" << local_addr << "/'</script>";
|
||||
|
||||
// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
|
||||
// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
|
||||
return res.write(buf) && res.write(NULL, 0);
|
||||
}
|
||||
|
||||
bool WebsocketServlet_impl::on_ping(const char *buf, unsigned long long len)
|
||||
{
|
||||
return send_pong();
|
||||
}
|
||||
|
||||
|
||||
bool WebsocketServlet_impl::on_pong(const char *buf, unsigned long long len)
|
||||
{
|
||||
return send_ping();
|
||||
}
|
||||
bool WebsocketServlet_impl::on_message(char *data, unsigned long long len, bool text)
|
||||
{
|
||||
switch (step_)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
printf("FileName:%s\n",data);
|
||||
filename_.append(data, len);
|
||||
step_++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
printf("FileSize:%s\n", data);
|
||||
filesize_ = std::strtol(data, 0, 10);
|
||||
step_++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (!file_)
|
||||
{
|
||||
file_ = new acl::ofstream();
|
||||
file_->open_trunc(filename_);
|
||||
}
|
||||
file_->write(data, len);
|
||||
current_filesize_ += len;
|
||||
if (current_filesize_ == filesize_)
|
||||
{
|
||||
printf("upload done\n");
|
||||
|
||||
file_->close();
|
||||
delete file_;
|
||||
file_ = NULL;
|
||||
filename_.clear();
|
||||
filesize_ = 0;
|
||||
current_filesize_ = 0;
|
||||
step_ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
class WebsocketServlet_impl : public acl::WebSocketServlet
|
||||
{
|
||||
public:
|
||||
WebsocketServlet_impl(acl::redis_client_cluster& cluster, size_t max_conns);
|
||||
~WebsocketServlet_impl();
|
||||
|
||||
acl::session& get_session() const
|
||||
{
|
||||
return *session_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool doUnknown(acl::HttpServletRequest&,
|
||||
acl::HttpServletResponse& res);
|
||||
virtual bool doGet(acl::HttpServletRequest& req,
|
||||
acl::HttpServletResponse& res);
|
||||
virtual bool doPost(acl::HttpServletRequest& req,
|
||||
acl::HttpServletResponse& res);
|
||||
|
||||
|
||||
//for websocket
|
||||
/**
|
||||
* websocket 关闭消息回调
|
||||
* @return {void}
|
||||
*/
|
||||
virtual void on_close()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* websocket ping 消息回调.
|
||||
* @param {const char *} buf 消息数据
|
||||
* @param {int} len 消息数据长度
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_ping(const char *buf, unsigned long long len);
|
||||
/**
|
||||
* websocket pong 消息回调.
|
||||
* @param {const char *} buf 消息数据
|
||||
* @param {int} len 消息数据长度
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_pong(const char *buf, unsigned long long len);
|
||||
|
||||
/**
|
||||
* websocket ping 消息回调.
|
||||
* @param data{char *} 回调数据缓存区。
|
||||
* @param len{unsigned long long}回调数据缓存区长度。
|
||||
* @param text{bool } true 为文本数据。否则是 二进制数据。
|
||||
* @return {bool} false 断开连接。
|
||||
*/
|
||||
virtual bool on_message(char *data, unsigned long long len, bool text);
|
||||
|
||||
private:
|
||||
acl::session* session_;
|
||||
|
||||
int step_;
|
||||
|
||||
acl::string filename_;
|
||||
|
||||
acl::ofstream *file_;
|
||||
|
||||
int filesize_;
|
||||
|
||||
int current_filesize_;
|
||||
};
|
37
lib_acl_cpp/samples/http/webSocketServlet/main.cpp
Normal file
37
lib_acl_cpp/samples/http/webSocketServlet/main.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "stdafx.h"
|
||||
#include "master_service.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// 初始化 acl 库
|
||||
acl::acl_cpp_init();
|
||||
|
||||
master_service& ms = acl::singleton2<master_service>::get_instance();
|
||||
|
||||
// 设置配置参数表
|
||||
ms.set_cfg_int(var_conf_int_tab);
|
||||
ms.set_cfg_int64(var_conf_int64_tab);
|
||||
ms.set_cfg_str(var_conf_str_tab);
|
||||
ms.set_cfg_bool(var_conf_bool_tab);
|
||||
|
||||
// 开始运行
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "alone") == 0)
|
||||
{
|
||||
acl::log::stdout_open(true); // 日志输出至标准输出
|
||||
const char* addr = "0.0.0.0:8888";
|
||||
//const char* addr = "/home/zsx/work/acl/trunk/app/wizard/http_server/http.sock";
|
||||
if (argc >= 3)
|
||||
addr = argv[2];
|
||||
|
||||
printf("listen on: %s\r\n", addr);
|
||||
ms.run_alone(addr, NULL, 0, 1000); // 单独运行方式
|
||||
|
||||
printf("Enter any key to exit now\r\n");
|
||||
getchar();
|
||||
}
|
||||
else
|
||||
ms.run_daemon(argc, argv); // acl_master 控制模式运行
|
||||
|
||||
return 0;
|
||||
}
|
132
lib_acl_cpp/samples/http/webSocketServlet/master_service.cpp
Normal file
132
lib_acl_cpp/samples/http/webSocketServlet/master_service.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "stdafx.h"
|
||||
#include "WebsocketServlet_impl.h"
|
||||
#include "master_service.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 配置内容项
|
||||
|
||||
char *var_cfg_redis_servers;
|
||||
acl::master_str_tbl var_conf_str_tab[] = {
|
||||
{ "redis_servers", "127.0.0.1:9000", &var_cfg_redis_servers },
|
||||
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
int var_cfg_keep_loop;
|
||||
acl::master_bool_tbl var_conf_bool_tab[] = {
|
||||
{ "keep_loop", false, &var_cfg_keep_loop },
|
||||
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
int var_cfg_conn_timeout;
|
||||
int var_cfg_rw_timeout;
|
||||
int var_cfg_max_threads;
|
||||
acl::master_int_tbl var_conf_int_tab[] = {
|
||||
{ "conn_timeout", 10, &var_cfg_conn_timeout, 0, 0 },
|
||||
{ "rw_timeout", 10, &var_cfg_rw_timeout, 0, 0 },
|
||||
{ "ioctl_max_threads", 128, &var_cfg_max_threads, 0, 0 },
|
||||
|
||||
{ 0, 0 , 0 , 0, 0 }
|
||||
};
|
||||
|
||||
long long int var_cfg_int64;
|
||||
acl::master_int64_tbl var_conf_int64_tab[] = {
|
||||
{ "int64", 120, &var_cfg_int64, 0, 0 },
|
||||
|
||||
{ 0, 0 , 0 , 0, 0 }
|
||||
};
|
||||
|
||||
static acl::redis_client_cluster* session_server = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
master_service::master_service()
|
||||
{
|
||||
}
|
||||
|
||||
master_service::~master_service()
|
||||
{
|
||||
}
|
||||
|
||||
bool master_service::thread_on_read(acl::socket_stream* conn)
|
||||
{
|
||||
//logger("read from %s", conn->get_peer(true));
|
||||
WebsocketServlet_impl* servlet = (WebsocketServlet_impl*) conn->get_ctx();
|
||||
if (servlet == NULL)
|
||||
logger_fatal("servlet null!");
|
||||
|
||||
acl::session& session = servlet->get_session();
|
||||
conn->set_rw_timeout(60);
|
||||
while (true)
|
||||
{
|
||||
bool ret = servlet->doRun(session, conn);
|
||||
if (ret == false)
|
||||
return false;
|
||||
if (!var_cfg_keep_loop)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool master_service::thread_on_accept(acl::socket_stream* conn)
|
||||
{
|
||||
logger("connect from %s, fd: %d", conn->get_peer(true),
|
||||
conn->sock_handle());
|
||||
conn->set_rw_timeout(0);
|
||||
|
||||
// 使用 redis 集群来存储 session
|
||||
WebsocketServlet_impl* servlet = new WebsocketServlet_impl(*session_server,
|
||||
var_cfg_max_threads);
|
||||
conn->set_ctx(servlet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool master_service::thread_on_timeout(acl::socket_stream* conn)
|
||||
{
|
||||
logger("read timeout from %s, fd: %d", conn->get_peer(),
|
||||
conn->sock_handle());
|
||||
return false;
|
||||
}
|
||||
|
||||
void master_service::thread_on_close(acl::socket_stream* conn)
|
||||
{
|
||||
logger("disconnect from %s, fd: %d", conn->get_peer(true),
|
||||
conn->sock_handle());
|
||||
|
||||
WebsocketServlet_impl* servlet = (WebsocketServlet_impl*) conn->get_ctx();
|
||||
if (servlet)
|
||||
delete servlet;
|
||||
}
|
||||
|
||||
void master_service::thread_on_init()
|
||||
{
|
||||
}
|
||||
|
||||
void master_service::thread_on_exit()
|
||||
{
|
||||
}
|
||||
|
||||
void master_service::proc_on_init()
|
||||
{
|
||||
// 创建 redis 集群客户端对象,并使用 redis 集群来存储 session
|
||||
session_server = new acl::redis_client_cluster;
|
||||
session_server->init(NULL, var_cfg_redis_servers, var_cfg_max_threads);
|
||||
}
|
||||
|
||||
bool master_service::proc_exit_timer(size_t nclients, size_t nthreads)
|
||||
{
|
||||
if (nclients == 0 || nthreads == 0)
|
||||
{
|
||||
logger("clients count: %d, threads count: %d",
|
||||
(int) nclients, (int) nthreads);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void master_service::proc_on_exit()
|
||||
{
|
||||
delete session_server;
|
||||
}
|
88
lib_acl_cpp/samples/http/webSocketServlet/master_service.h
Normal file
88
lib_acl_cpp/samples/http/webSocketServlet/master_service.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 配置内容项
|
||||
|
||||
extern acl::master_str_tbl var_conf_str_tab[];
|
||||
extern acl::master_bool_tbl var_conf_bool_tab[];
|
||||
extern acl::master_int_tbl var_conf_int_tab[];
|
||||
extern acl::master_int64_tbl var_conf_int64_tab[];
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//class acl::socket_stream;
|
||||
|
||||
class master_service : public acl::master_threads
|
||||
{
|
||||
public:
|
||||
master_service();
|
||||
~master_service();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* 纯虚函数:当某个客户端连接有数据可读或关闭或出错时调用此函数
|
||||
* @param stream {socket_stream*}
|
||||
* @return {bool} 返回 false 则表示当函数返回后需要关闭连接,
|
||||
* 否则表示需要保持长连接,如果该流出错,则应用应该返回 false
|
||||
*/
|
||||
virtual bool thread_on_read(acl::socket_stream* stream);
|
||||
|
||||
/**
|
||||
* 当线程池中的某个线程获得一个连接时的回调函数,
|
||||
* 子类可以做一些初始化工作
|
||||
* @param stream {socket_stream*}
|
||||
* @return {bool} 如果返回 false 则表示子类要求关闭连接,而不
|
||||
* 必将该连接再传递至 thread_main 过程
|
||||
*/
|
||||
virtual bool thread_on_accept(acl::socket_stream* stream);
|
||||
|
||||
/**
|
||||
* 当某个网络连接的 IO 读写超时时的回调函数,如果该函数返回 true 则表示继续等待下一次
|
||||
* 读写,否则则希望关闭该连接
|
||||
* @param stream {socket_stream*}
|
||||
* @return {bool} 如果返回 false 则表示子类要求关闭连接,而不
|
||||
* 必将该连接再传递至 thread_main 过程
|
||||
*/
|
||||
virtual bool thread_on_timeout(acl::socket_stream* stream);
|
||||
|
||||
/**
|
||||
* 当与某个线程绑定的连接关闭时的回调函数
|
||||
* @param stream {socket_stream*}
|
||||
*/
|
||||
virtual void thread_on_close(acl::socket_stream* stream);
|
||||
|
||||
/**
|
||||
* 当线程池中一个新线程被创建时的回调函数
|
||||
*/
|
||||
virtual void thread_on_init();
|
||||
|
||||
/**
|
||||
* 当线程池中一个线程退出时的回调函数
|
||||
*/
|
||||
virtual void thread_on_exit();
|
||||
|
||||
/**
|
||||
* 当进程切换用户身份后调用的回调函数,此函数被调用时,进程
|
||||
* 的权限为普通受限级别
|
||||
*/
|
||||
virtual void proc_on_init();
|
||||
|
||||
/**
|
||||
* 当子进程需要退出时框架将回调此函数,框架决定子进程是否退出取决于:
|
||||
* 1) 如果此函数返回 true 则子进程立即退出,否则:
|
||||
* 2) 如果该子进程所有客户端连接都已关闭,则子进程立即退出,否则:
|
||||
* 3) 查看配置文件中的配置项(ioctl_quick_abort),如果该配置项非 0 则
|
||||
* 子进程立即退出,否则:
|
||||
* 4) 等所有客户端连接关闭后才退出
|
||||
* @param ncleints {size_t} 当前连接的客户端个数
|
||||
* @param nthreads {size_t} 当前线程池中繁忙的工作线程个数
|
||||
* @return {bool} 返回 false 表示当前子进程还不能退出,否则表示当前
|
||||
* 子进程可以退出了
|
||||
*/
|
||||
virtual bool proc_exit_timer(size_t nclients, size_t nthreads);
|
||||
|
||||
/**
|
||||
* 当进程退出前调用的回调函数
|
||||
*/
|
||||
virtual void proc_on_exit();
|
||||
};
|
8
lib_acl_cpp/samples/http/webSocketServlet/stdafx.cpp
Normal file
8
lib_acl_cpp/samples/http/webSocketServlet/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// master_threads.pch 将成为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中
|
||||
//引用任何所需的附加头文件,而不是在此文件中引用
|
19
lib_acl_cpp/samples/http/webSocketServlet/stdafx.h
Normal file
19
lib_acl_cpp/samples/http/webSocketServlet/stdafx.h
Normal file
@ -0,0 +1,19 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是常用但不常更改的项目特定的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
//#include <tchar.h>
|
||||
|
||||
// TODO: 在此处引用程序要求的附加头文件
|
||||
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
#include "lib_acl.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{EAF88147-3FB2-4FCD-A81C-50E233C68282}</ProjectGuid>
|
||||
<RootNamespace>webSocketServlet</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\lib_acl_cpp\include;..\..\..\..\lib_acl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp_vc2015d.lib;lib_acl_vc2015d.lib;lib_protocol_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\lib_acl_cpp\include;..\..\..\..\lib_acl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_cpp_vc2015d.lib;lib_acl_vc2015d.lib;lib_protocol_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\lib_acl_cpp\include;..\..\..\..\lib_acl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\lib_acl_cpp\include;..\..\..\..\lib_acl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="WebsocketServlet_impl.h" />
|
||||
<ClInclude Include="master_service.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="WebsocketServlet_impl.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="master_service.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\lib_acl_cpp_vc2015.vcxproj">
|
||||
<Project>{6ec1f44e-6a6a-48e9-b699-d7e89b63c8dc}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="master_service.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WebsocketServlet_impl.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="master_service.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WebsocketServlet_impl.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
106
lib_acl_cpp/samples/http/webSocketServlet/www/upload.html
Normal file
106
lib_acl_cpp/samples/http/webSocketServlet/www/upload.html
Normal file
@ -0,0 +1,106 @@
|
||||
<html>
|
||||
<meta charset="utf-8" />
|
||||
<title>WebSocket Test</title>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"> 分段读取文件:</div>
|
||||
<div class="panel-body">
|
||||
<input type="file" id="fileId" /><br />
|
||||
<input type="button" value="中止" onclick="stop();" /> <br />
|
||||
<input type="button" value="继续" onclick="goon();" />
|
||||
<progress id="progressOne" style="width:400px;" max="100" value="0"></progress>
|
||||
<blockquote id="status" style="word-break:break-all;"></blockquote>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://github.com/zhengshuxin/acl/tree/master/lib_acl_cpp/samples/websocket/upload_server" target=_blank>源码</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
var g_url = null;
|
||||
var g_ws = null;
|
||||
var g_fileBox = document.getElementById('fileId');
|
||||
var g_reader = null;
|
||||
var g_step = 1024 * 128;
|
||||
var g_loaded = 0;
|
||||
var g_total = 0;
|
||||
var g_file = null;
|
||||
var g_enableRead = true;
|
||||
|
||||
g_fileBox.onchange = function() {
|
||||
g_file = this.files[0];
|
||||
g_total = g_file.size;
|
||||
if (g_ws == null)
|
||||
createSocket(function() { bindReader(); });
|
||||
else
|
||||
bindReader();
|
||||
}
|
||||
|
||||
function bindReader() {
|
||||
g_loaded = 0;
|
||||
g_reader = new FileReader();
|
||||
g_reader.onload = function(e) {
|
||||
if (g_enableRead == false)
|
||||
return;
|
||||
if (g_ws.bufferedAmount > g_step * 10)
|
||||
setTimeout(function() { loadSuccess(e.loaded); }, 100);
|
||||
else
|
||||
loadSuccess(e.loaded);
|
||||
}
|
||||
|
||||
readBlob();
|
||||
}
|
||||
|
||||
function loadSuccess(loaded) {
|
||||
var blob = g_reader.result;
|
||||
if (g_loaded == 0) {
|
||||
g_ws.send(g_file.name);
|
||||
var len = "" + g_file.size;
|
||||
g_ws.send(len);
|
||||
}
|
||||
|
||||
g_ws.send(blob);
|
||||
g_loaded += loaded;
|
||||
|
||||
if (g_loaded < g_total)
|
||||
readBlob();
|
||||
var percent = Math.round((g_loaded * 100) / g_total);
|
||||
document.getElementById('status').innerText = percent + "%";
|
||||
document.getElementById('progressOne').value = percent;
|
||||
}
|
||||
|
||||
function readBlob() {
|
||||
var blob = g_file.slice(g_loaded, g_loaded + g_step);
|
||||
g_reader.readAsArrayBuffer(blob);
|
||||
}
|
||||
|
||||
function stop() {
|
||||
g_enableRead = false;
|
||||
g_reader.abort();
|
||||
}
|
||||
|
||||
function goon() {
|
||||
g_enableRead = true;
|
||||
readBlob();
|
||||
}
|
||||
|
||||
function createSocket(onSuccess) {
|
||||
g_ws = new WebSocket(g_url);
|
||||
g_ws.onopen = function() {
|
||||
if (onSuccess)
|
||||
onSuccess();
|
||||
g_ws.onmessage = function(e) {}
|
||||
}
|
||||
g_ws.onclose = function(e) { g_ws.close(); g_ws = null; }
|
||||
g_ws.onerror = function(e) { g_ws.close(); g_ws = null; }
|
||||
}
|
||||
|
||||
function test() {
|
||||
var o = document.getElementById('fileId');
|
||||
alert("o: " + o);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,399 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2015-2018
|
||||
* All rights reserved.
|
||||
*
|
||||
* AUTHOR(S)
|
||||
* Zheng Shuxin
|
||||
* E-mail: zhengshuxin@qiyi.com
|
||||
*
|
||||
* VERSION
|
||||
* Thu 30 May 2017 05:25:43 PM CST
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "udp.h"
|
||||
|
||||
static bool host_port(char *buf, char **host, char **port)
|
||||
{
|
||||
const char *ptr = acl_host_port(buf, host, "", port, (char*) NULL);
|
||||
|
||||
if (ptr != NULL) {
|
||||
acl_msg_error("%s(%d): invalid addr %s, %s",
|
||||
__FILE__, __LINE__, buf, ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*port == NULL || atoi(*port) < 0) {
|
||||
acl_msg_error("%s(%d): invalid port: %s, addr: %s",
|
||||
__FILE__, __LINE__, *port ? *port : "null", buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*host && **host == 0)
|
||||
*host = 0;
|
||||
if (*host == NULL)
|
||||
*host = "0";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct addrinfo *host_addrinfo(const char *addr)
|
||||
{
|
||||
int err;
|
||||
struct addrinfo hints, *res0;
|
||||
char *buf = acl_mystrdup(addr), *host = NULL, *port = NULL;
|
||||
|
||||
if (host_port(buf, &host, &port) == false) {
|
||||
acl_myfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
#ifdef ACL_MACOSX
|
||||
hints.ai_flags = AI_DEFAULT;
|
||||
#elif defined(ACL_ANDROID)
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
#elif defined(ACL_WINDOWS)
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
# if _MSC_VER >= 1500
|
||||
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
|
||||
# endif
|
||||
#else
|
||||
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
|
||||
#endif
|
||||
if ((err = getaddrinfo(host, port, &hints, &res0))) {
|
||||
acl_msg_error("%s(%d): getaddrinfo error %s, peer=%s",
|
||||
__FILE__, __LINE__, gai_strerror(err), host);
|
||||
acl_myfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acl_myfree(buf);
|
||||
return res0;
|
||||
}
|
||||
|
||||
static int bind_addr(struct addrinfo *res0, struct addrinfo **res)
|
||||
{
|
||||
struct addrinfo *it;
|
||||
int on, fd;
|
||||
|
||||
for (it = res0; it != NULL ; it = it->ai_next) {
|
||||
fd = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
|
||||
if (fd == ACL_SOCKET_INVALID) {
|
||||
acl_msg_error("%s(%d): create socket %s",
|
||||
__FILE__, __LINE__, acl_last_serror());
|
||||
return ACL_SOCKET_INVALID;
|
||||
}
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *) &on, sizeof(on)) < 0)
|
||||
{
|
||||
acl_msg_warn("%s(%d): setsockopt(SO_REUSEADDR): %s",
|
||||
__FILE__, __LINE__, acl_last_serror());
|
||||
}
|
||||
|
||||
#if defined(SO_REUSEPORT)
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
|
||||
(const void *) &on, sizeof(on)) < 0)
|
||||
{
|
||||
acl_msg_warn("%s(%d): setsocket(SO_REUSEPORT): %s",
|
||||
__FILE__, __LINE__, acl_last_serror());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ACL_WINDOWS
|
||||
if (bind(fd, it->ai_addr, (int) it->ai_addrlen) == 0)
|
||||
#else
|
||||
if (bind(fd, it->ai_addr, it->ai_addrlen) == 0)
|
||||
#endif
|
||||
{
|
||||
*res = it;
|
||||
return fd;
|
||||
}
|
||||
|
||||
acl_msg_error("%s(%d): bind error %s",
|
||||
__FILE__, __LINE__, acl_last_serror());
|
||||
acl_socket_close(fd);
|
||||
}
|
||||
|
||||
return ACL_SOCKET_INVALID;
|
||||
}
|
||||
|
||||
udp_pkt::udp_pkt(size_t size /* = 1460 */)
|
||||
: size_(size)
|
||||
{
|
||||
acl_assert(size >= 1460);
|
||||
iov_.iov_base = acl_mymalloc(size);
|
||||
iov_.iov_len = size;
|
||||
}
|
||||
|
||||
udp_pkt::~udp_pkt(void)
|
||||
{
|
||||
acl_myfree(iov_.iov_base);
|
||||
}
|
||||
|
||||
bool udp_pkt::set_data(const void* data, size_t len)
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
logger_error("data null");
|
||||
return false;
|
||||
}
|
||||
if (len == 0 || len > size_)
|
||||
{
|
||||
logger_error("invalid len=%lu", len);
|
||||
return false;
|
||||
}
|
||||
memcpy(iov_.iov_base, data, len);
|
||||
iov_.iov_len = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udp_pkt::set_peer(const char* addr)
|
||||
{
|
||||
struct addrinfo *peer_res0 = host_addrinfo(addr);
|
||||
|
||||
if (peer_res0 == NULL)
|
||||
return false;
|
||||
|
||||
memcpy(&addr_, peer_res0->ai_addr, peer_res0->ai_addrlen);
|
||||
addr_len_ = peer_res0->ai_addrlen;
|
||||
freeaddrinfo(peer_res0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int udp_pkt::get_port(void) const
|
||||
{
|
||||
if (addr_.sa.sa.sa_family == AF_INET)
|
||||
{
|
||||
const struct sockaddr_in *in = &addr_.sa.in;
|
||||
return ntohs(in->sin_port);
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (addr_.sa.sa.sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *in = &addr_.sa.in6;
|
||||
return ntohl(in->sin6_port);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
logger_error("unkown sa_family=%d", addr_.sa.sa.sa_family);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *udp_pkt::get_ip(char* buf, size_t size) const
|
||||
{
|
||||
if (addr_.sa.sa.sa_family == AF_INET)
|
||||
{
|
||||
const struct sockaddr_in *in = &addr_.sa.in;
|
||||
return inet_ntop(in->sin_family, &in->sin_addr, buf, size);
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (addr_.sa.sa.sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *in = &addr_.sa.in6;
|
||||
return inet_ntop(in->sin6_family, &in->sin6_addr, buf, size);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
logger_error("unkown sa_family=%d", addr_.sa.sa.sa_family);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
udp_pkts::udp_pkts(size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
udp_pkt* pkt = new udp_pkt;
|
||||
pkts_.push_back(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
udp_pkts::~udp_pkts(void)
|
||||
{
|
||||
for (std::vector<udp_pkt*>::iterator it = pkts_.begin();
|
||||
it != pkts_.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
udp_pkt* udp_pkts::operator[](size_t i)
|
||||
{
|
||||
if (i >= pkts_.size())
|
||||
return NULL;
|
||||
return pkts_[i];
|
||||
}
|
||||
|
||||
udp_sock::udp_sock(void)
|
||||
: fd_(ACL_SOCKET_INVALID)
|
||||
, msgvec_(NULL)
|
||||
, vlen_(0)
|
||||
{
|
||||
}
|
||||
|
||||
udp_sock::~udp_sock(void)
|
||||
{
|
||||
acl_myfree(msgvec_);
|
||||
if (fd_ != ACL_SOCKET_INVALID)
|
||||
acl_socket_close(fd_);
|
||||
}
|
||||
|
||||
bool udp_sock::bind(const char* addr)
|
||||
{
|
||||
struct addrinfo *res0, *res;
|
||||
|
||||
res0 = host_addrinfo(addr);
|
||||
if (res0 == NULL)
|
||||
return false;
|
||||
|
||||
fd_ = bind_addr(res0, &res);
|
||||
if (fd_ == ACL_SOCKET_INVALID)
|
||||
{
|
||||
logger_error("invalid socket");
|
||||
freeaddrinfo(res0);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&sa_local_, res->ai_addr, res->ai_addrlen);
|
||||
sa_local_len_ = res->ai_addrlen;
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udp_sock::server_open(const char *local)
|
||||
{
|
||||
return bind(local);
|
||||
}
|
||||
|
||||
bool udp_sock::client_open(const char *local, const char *peer)
|
||||
{
|
||||
struct addrinfo *peer_res0 = host_addrinfo(peer);
|
||||
|
||||
if (peer_res0 == NULL)
|
||||
return NULL;
|
||||
|
||||
if (bind(local) == false)
|
||||
{
|
||||
freeaddrinfo(peer_res0);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&sa_peer_, peer_res0->ai_addr, peer_res0->ai_addrlen);
|
||||
sa_peer_len_ = peer_res0->ai_addrlen;
|
||||
freeaddrinfo(peer_res0);
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t udp_sock::send(const void *data, size_t len)
|
||||
{
|
||||
return sendto(fd_, data, len, 0,
|
||||
(struct sockaddr *) &sa_peer_, sa_peer_len_);
|
||||
}
|
||||
|
||||
ssize_t udp_sock::recv(void *buf, size_t size)
|
||||
{
|
||||
sa_peer_len_ = sizeof(sa_peer_);
|
||||
return recvfrom(fd_, buf, size, 0,
|
||||
(struct sockaddr *) &sa_peer_, &sa_peer_len_);
|
||||
}
|
||||
|
||||
int udp_sock::send(std::vector<udp_pkt*>& pkts, size_t max)
|
||||
{
|
||||
size_t pkts_cnt = pkts.size();
|
||||
if (pkts_cnt >= max)
|
||||
pkts_cnt = max;
|
||||
|
||||
if (msgvec_ == NULL)
|
||||
{
|
||||
vlen_ = pkts_cnt;
|
||||
msgvec_ = (struct mmsghdr *)
|
||||
acl_mycalloc(pkts_cnt, sizeof(struct mmsghdr));
|
||||
}
|
||||
else if (vlen_ < pkts_cnt)
|
||||
{
|
||||
acl_myfree(msgvec_);
|
||||
vlen_ = pkts_cnt;
|
||||
msgvec_ = (struct mmsghdr *)
|
||||
acl_mycalloc(pkts_cnt, sizeof(struct mmsghdr));
|
||||
}
|
||||
|
||||
unsigned int flags = 0;
|
||||
memset(msgvec_, 0, sizeof(struct mmsghdr) * pkts_cnt);
|
||||
|
||||
#ifndef __linux3__
|
||||
int n = 0;
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < pkts_cnt; i++)
|
||||
{
|
||||
msgvec_[i].msg_hdr.msg_iov = &pkts[i]->iov_;
|
||||
msgvec_[i].msg_hdr.msg_iovlen = 1;
|
||||
msgvec_[i].msg_hdr.msg_name = &pkts[i]->addr_;
|
||||
msgvec_[i].msg_hdr.msg_namelen = sizeof(pkts[i]->addr_);
|
||||
msgvec_[i].msg_len = 0;
|
||||
#ifndef __linux3__
|
||||
if (sendmsg(fd_, &msgvec_[i].msg_hdr, flags) < 0)
|
||||
return -1;
|
||||
n++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux3__
|
||||
return sendmmsg(fd_, msgvec_, pkts_cnt, flags);
|
||||
#else
|
||||
return n;
|
||||
#endif
|
||||
}
|
||||
|
||||
int udp_sock::recv(std::vector<udp_pkt*>& pkts)
|
||||
{
|
||||
unsigned int flags = MSG_WAITFORONE /* | MSG_DONTWAIT */;
|
||||
size_t pkts_cnt = pkts.size();
|
||||
|
||||
if (msgvec_ == NULL)
|
||||
{
|
||||
vlen_ = pkts_cnt;
|
||||
msgvec_ = (struct mmsghdr *)
|
||||
acl_mycalloc(pkts_cnt, sizeof(struct mmsghdr));
|
||||
}
|
||||
else if (vlen_ < pkts_cnt)
|
||||
{
|
||||
acl_myfree(msgvec_);
|
||||
vlen_ = pkts_cnt;
|
||||
msgvec_ = (struct mmsghdr *)
|
||||
acl_mycalloc(pkts_cnt, sizeof(struct mmsghdr));
|
||||
}
|
||||
|
||||
memset(msgvec_, 0, sizeof(struct mmsghdr) * pkts_cnt);
|
||||
|
||||
int i = 0;
|
||||
for (std::vector<udp_pkt*>::iterator it = pkts.begin();
|
||||
it != pkts.end(); ++it)
|
||||
{
|
||||
(*it)->iov_.iov_len = (*it)->size_;
|
||||
msgvec_[i].msg_hdr.msg_iov = &(*it)->iov_;
|
||||
msgvec_[i].msg_hdr.msg_iovlen = 1;
|
||||
msgvec_[i].msg_hdr.msg_name = &(*it)->addr_;
|
||||
msgvec_[i].msg_hdr.msg_namelen = sizeof((*it)->addr_);
|
||||
msgvec_[i].msg_len = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
int ret = recvmmsg(fd_, msgvec_, pkts_cnt, flags, NULL);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ret; i++)
|
||||
msgvec_[i].msg_hdr.msg_iov->iov_len = msgvec_[i].msg_len;
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2015-2018
|
||||
* All rights reserved.
|
||||
*
|
||||
* AUTHOR(S)
|
||||
* Zheng Shuxin
|
||||
* E-mail: zhengshuxin@qiyi.com
|
||||
*
|
||||
* VERSION
|
||||
* Thu 30 May 2017 05:26:42 PM CST
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
#include <vector>
|
||||
|
||||
typedef struct SOCK_ADDR {
|
||||
union {
|
||||
struct sockaddr_storage ss;
|
||||
#ifdef AF_INET6
|
||||
struct sockaddr_in6 in6;
|
||||
#endif
|
||||
struct sockaddr_in in;
|
||||
#ifdef ACL_UNIX
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
struct sockaddr sa;
|
||||
} sa;
|
||||
} SOCK_ADDR;
|
||||
|
||||
class udp_sock;
|
||||
|
||||
class udp_pkt
|
||||
{
|
||||
public:
|
||||
udp_pkt(size_t size = 1460);
|
||||
~udp_pkt(void);
|
||||
|
||||
bool set_data(const void* data, size_t len);
|
||||
bool set_peer(const char* addr);
|
||||
|
||||
void* get_data(void) const
|
||||
{
|
||||
return iov_.iov_base;
|
||||
}
|
||||
|
||||
size_t get_dlen(void) const
|
||||
{
|
||||
return iov_.iov_len;
|
||||
}
|
||||
|
||||
int get_port(void) const;
|
||||
const char* get_ip(char* buf, size_t len) const;
|
||||
|
||||
private:
|
||||
friend class udp_sock;
|
||||
|
||||
struct iovec iov_;
|
||||
const size_t size_;
|
||||
SOCK_ADDR addr_;
|
||||
socklen_t addr_len_;
|
||||
};
|
||||
|
||||
class udp_pkts
|
||||
{
|
||||
public:
|
||||
udp_pkts(size_t n);
|
||||
~udp_pkts(void);
|
||||
|
||||
udp_pkt* operator[](size_t i);
|
||||
|
||||
std::vector<udp_pkt*>& get_pkts(void)
|
||||
{
|
||||
return pkts_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<udp_pkt*> pkts_;
|
||||
};
|
||||
|
||||
class udp_sock
|
||||
{
|
||||
public:
|
||||
udp_sock(void);
|
||||
~udp_sock(void);
|
||||
|
||||
bool bind(const char* addr);
|
||||
bool client_open(const char* local, const char* peer);
|
||||
bool server_open(const char* local);
|
||||
|
||||
ssize_t send(const void* data, size_t len);
|
||||
ssize_t recv(void* buf, size_t len);
|
||||
|
||||
int recv(std::vector<udp_pkt*>& pkts);
|
||||
int send(std::vector<udp_pkt*>& pkts, size_t max);
|
||||
|
||||
private:
|
||||
int fd_;
|
||||
|
||||
SOCK_ADDR sa_local_;
|
||||
socklen_t sa_local_len_;
|
||||
|
||||
SOCK_ADDR sa_peer_;
|
||||
socklen_t sa_peer_len_;
|
||||
|
||||
struct mmsghdr* msgvec_;
|
||||
size_t vlen_;
|
||||
};
|
@ -151,6 +151,11 @@ void query::del_param(const string& key)
|
||||
}
|
||||
}
|
||||
|
||||
query& query::set_parameter(const char* name, const std::string &value)
|
||||
{
|
||||
return set_parameter(name, value.c_str());
|
||||
}
|
||||
|
||||
query& query::set_parameter(const char* name, const char *value)
|
||||
{
|
||||
string key(name);
|
||||
|
181
lib_acl_cpp/src/http/WebSocketServlet.cpp
Normal file
181
lib_acl_cpp/src/http/WebSocketServlet.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include "acl_stdafx.hpp"
|
||||
#ifndef ACL_PREPARE_COMPILE
|
||||
#include "acl_cpp/stdlib/log.hpp"
|
||||
#include "acl_cpp/stream/socket_stream.hpp"
|
||||
#include "acl_cpp/http/WebSocketServlet.hpp"
|
||||
#endif
|
||||
|
||||
namespace acl
|
||||
{
|
||||
WebSocketServlet::WebSocketServlet(socket_stream* stream, session* session)
|
||||
:HttpServlet(stream, session),
|
||||
max_msg_len_(100 * 1024*1024),
|
||||
ws_(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebSocketServlet::WebSocketServlet(
|
||||
socket_stream* stream,
|
||||
const char* memcache_addr )
|
||||
:HttpServlet(stream, memcache_addr),
|
||||
max_msg_len_(100 * 1024 * 1024),
|
||||
ws_(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebSocketServlet::WebSocketServlet()
|
||||
:max_msg_len_(100 * 1024 * 1024),
|
||||
ws_(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebSocketServlet::~WebSocketServlet()
|
||||
{
|
||||
if (ws_)
|
||||
delete ws_;
|
||||
ws_ = NULL;
|
||||
}
|
||||
|
||||
bool WebSocketServlet::doRun()
|
||||
{
|
||||
if (!ws_)
|
||||
{
|
||||
bool ret = HttpServlet::doRun();
|
||||
//websocket upgrade ok.
|
||||
//maybe http without keepalive ,
|
||||
//return false,framework will close this connection.
|
||||
if (ws_)
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ws_->read_frame_head() == false)
|
||||
return false;
|
||||
|
||||
unsigned long long len = ws_->get_frame_payload_len();
|
||||
if (len > max_msg_len_)
|
||||
{
|
||||
logger_error("payload too large error: %llu", len);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
if (!recv_buffer_)
|
||||
{
|
||||
recv_buffer_ = (char*)acl_mymalloc((size_t)len + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//frame not finish.
|
||||
recv_buffer_ = (char*)acl_myrealloc(recv_buffer_, write_pos_ + (size_t)len + 1);
|
||||
}
|
||||
|
||||
if (ws_->read_frame_data(recv_buffer_+ write_pos_, len) < 0)
|
||||
{
|
||||
write_pos_ = 0;
|
||||
acl_myfree(recv_buffer_);
|
||||
recv_buffer_ = NULL;
|
||||
return false;
|
||||
}
|
||||
write_pos_ += len;
|
||||
recv_buffer_[write_pos_] = '\0';
|
||||
}
|
||||
int opcode = ws_->get_frame_opcode();
|
||||
bool ret = false;
|
||||
|
||||
if (ws_->get_frame_fin() == false)
|
||||
{
|
||||
//safe opcode.
|
||||
if(opcode != FRAME_CONTINUATION)
|
||||
opcode_ = opcode;
|
||||
return true;
|
||||
}
|
||||
|
||||
//frame is finish callback frame.
|
||||
if (opcode == FRAME_CONTINUATION)
|
||||
{
|
||||
opcode = opcode_;
|
||||
}
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case FRAME_PING:
|
||||
ret = on_ping(recv_buffer_, write_pos_);
|
||||
break;
|
||||
case FRAME_PONG:
|
||||
ret = on_pong(recv_buffer_, write_pos_);
|
||||
break;
|
||||
case FRAME_CLOSE:
|
||||
on_close();
|
||||
break;
|
||||
case FRAME_TEXT:
|
||||
case FRAME_BINARY:
|
||||
{
|
||||
ret = on_message(recv_buffer_, write_pos_,
|
||||
ws_->get_frame_opcode() == FRAME_TEXT);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logger_error("unknown websocket Frame opcode error: %d",
|
||||
ws_->get_frame_opcode());
|
||||
}
|
||||
if (recv_buffer_)
|
||||
{
|
||||
acl_myfree(recv_buffer_);
|
||||
recv_buffer_ = NULL;
|
||||
write_pos_ = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool WebSocketServlet::send_binary(const char *recv_buffer_, int len)
|
||||
{
|
||||
ws_->set_frame_opcode(FRAME_BINARY);
|
||||
ws_->set_frame_fin(true);
|
||||
ws_->set_frame_payload_len(len);
|
||||
return ws_->send_frame_data(recv_buffer_, len);
|
||||
}
|
||||
|
||||
bool WebSocketServlet::send_text(const char *recv_buffer_fer)
|
||||
{
|
||||
ws_->set_frame_opcode(FRAME_TEXT);
|
||||
ws_->set_frame_fin(true);
|
||||
ws_->set_frame_payload_len(strlen(recv_buffer_fer));
|
||||
return ws_->send_frame_data(recv_buffer_fer, strlen(recv_buffer_fer));
|
||||
}
|
||||
|
||||
bool WebSocketServlet::send_pong(const char *text)
|
||||
{
|
||||
size_t len = !text ? 0 : strlen(text);
|
||||
ws_->set_frame_opcode(FRAME_PONG);
|
||||
ws_->set_frame_fin(true);
|
||||
ws_->set_frame_payload_len(len);
|
||||
return ws_->send_frame_data(text, len);
|
||||
}
|
||||
|
||||
bool WebSocketServlet::send_ping(const char *text)
|
||||
{
|
||||
size_t len = !text ? 0 : strlen(text);
|
||||
ws_->set_frame_opcode(FRAME_PING);
|
||||
ws_->set_frame_fin(true);
|
||||
ws_->set_frame_payload_len(len);
|
||||
return ws_->send_frame_data(text, len);
|
||||
}
|
||||
|
||||
bool WebSocketServlet::doWebsocket(HttpServletRequest&, HttpServletResponse&)
|
||||
{
|
||||
acl_assert(!ws_);
|
||||
ws_ = new websocket(*getStream());
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebSocketServlet::on_close()
|
||||
{
|
||||
}
|
||||
}
|
@ -361,25 +361,33 @@ int websocket::read_frame_data(char* buf, size_t size)
|
||||
if (header_.payload_len - payload_nread_ < size)
|
||||
size = (size_t) (header_.payload_len - payload_nread_);
|
||||
|
||||
int ret = client_.read(buf, size, false);
|
||||
if (ret == -1)
|
||||
int bytes = 0;
|
||||
while (true)
|
||||
{
|
||||
if (last_error() != ACL_ETIMEDOUT)
|
||||
logger_error("read frame data error: %d, %s",
|
||||
last_error(), last_serror());
|
||||
return -1;
|
||||
int ret = client_.read(buf + bytes, size - bytes, false);
|
||||
if (ret == -1)
|
||||
{
|
||||
if (last_error() != ACL_ETIMEDOUT)
|
||||
logger_error("read frame data error: %d, %s",
|
||||
last_error(), last_serror());
|
||||
return -1;
|
||||
}
|
||||
bytes += ret;
|
||||
if (bytes == size)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (header_.mask)
|
||||
{
|
||||
unsigned char* mask = (unsigned char*) &header_.masking_key;
|
||||
for (int i = 0; i < ret; i++)
|
||||
for (int i = 0; i < bytes; i++)
|
||||
buf[i] ^= mask[i % 4];
|
||||
}
|
||||
|
||||
payload_nread_ += ret;
|
||||
payload_nread_ += bytes;
|
||||
|
||||
return ret;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
} // namespace acl
|
||||
|
@ -553,6 +553,26 @@ again:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool gsoner::check_using_namespace()
|
||||
{
|
||||
//
|
||||
using namespace std;
|
||||
std::string token = codes_.substr(pos_, strlen("using"));
|
||||
if (token == "using")
|
||||
{
|
||||
pos_ += (int)strlen("using");
|
||||
skip_space_comment();
|
||||
token = codes_.substr(pos_, strlen("namespace"));
|
||||
if (token != "namespace")
|
||||
throw syntax_error();
|
||||
pos_ += (int)strlen("namespace");
|
||||
skip_space_comment();
|
||||
token = next_token("; ");
|
||||
std::cout << "find using nameapace " << token << std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool gsoner::check_include()
|
||||
{
|
||||
std::string tmp = codes_.substr(pos_, strlen("#include"));
|
||||
@ -1334,6 +1354,9 @@ void gsoner::parse_code()
|
||||
continue;
|
||||
if(check_namespace_end())
|
||||
continue;
|
||||
case 'u':
|
||||
if(check_using_namespace())
|
||||
continue;
|
||||
case 'n':
|
||||
if(check_namespace())
|
||||
continue;
|
||||
|
205
lib_acl_cpp1z/include/lib_acl_cpp1z/db/db_mysql.hpp
Normal file
205
lib_acl_cpp1z/include/lib_acl_cpp1z/db/db_mysql.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "acl_cpp/db/db_mysql.hpp"
|
||||
#include "lib_acl_cpp1z/reflection/reflection.hpp"
|
||||
namespace acl
|
||||
{
|
||||
namespace lz
|
||||
{
|
||||
|
||||
class db_mysql : public acl::db_mysql
|
||||
{
|
||||
public:
|
||||
struct date
|
||||
{
|
||||
time_t value;
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* 构造函数方式一
|
||||
* @param dbaddr {const char*} 数据库监听地址,可以为 TCP 套接口或在 UNIX
|
||||
* 平台下的域套接口,格式如:127.0.0.1:3306,或 /tmp/mysql.sock
|
||||
* @param dbname {const char*} 数据库名称,非 NULL
|
||||
* @param dbuser {const char*} 连接数据库时的用户名
|
||||
* @param dbpass {const char*} 连接数据库时的用户密码
|
||||
* @param dbflags {unsigned long} 连接 MYSQL 时的标志位
|
||||
* @param auto_commit {bool} 当对数据库进行修改时是否自动提交事务
|
||||
* @param conn_timeout {int} 连接数据库的超时时间(秒)
|
||||
* @param rw_timeout {int} 进行数据库操作时的超时时间(秒)
|
||||
* @param charset {const char*} 连接数据库时的本地字符集(gbk, utf8, ...)
|
||||
*/
|
||||
|
||||
db_mysql(const char* dbaddr, const char* dbname,
|
||||
const char* dbuser, const char* dbpass,
|
||||
unsigned long dbflags = 0, bool auto_commit = true,
|
||||
int conn_timeout = 60, int rw_timeout = 60,
|
||||
const char* charset = "utf8")
|
||||
:acl::db_mysql(
|
||||
dbaddr,
|
||||
dbname,
|
||||
dbuser,
|
||||
dbpass,
|
||||
dbflags,
|
||||
auto_commit,
|
||||
conn_timeout,
|
||||
rw_timeout,
|
||||
charset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数方式二:使用参数配置类对象进行构造
|
||||
* @param conf {const mysql_conf&} mysql 数据库连接配置类对象
|
||||
*/
|
||||
db_mysql(const mysql_conf& conf)
|
||||
:acl::db_mysql(conf)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::enable_if_t<(sizeof...(Args) == 0), std::pair<bool, std::vector<T>>>
|
||||
select(const char *sql)
|
||||
{
|
||||
std::vector<T> v;
|
||||
|
||||
if (!sql_select(sql))
|
||||
return{ false, {} };
|
||||
for (size_t i = 0; i < length(); i++)
|
||||
{
|
||||
T t;
|
||||
const acl::db_row* row = (*this)[i];
|
||||
for_each(t, [&](auto& item, size_t I, bool is_last)
|
||||
{
|
||||
const char * row_name = get_name<T>(I);
|
||||
const char * value = (*row)[row_name];
|
||||
if (!value)
|
||||
return;
|
||||
assign(item, value);
|
||||
});
|
||||
v.push_back(t);
|
||||
}
|
||||
return{ true, v };
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::enable_if_t<(sizeof...(Args) == 0), bool>
|
||||
select(const char *sql, std::string &json_str)
|
||||
{
|
||||
if (!sql_select(sql))
|
||||
return false;
|
||||
json_str.push_back('[');
|
||||
|
||||
for (size_t i = 0; i < length(); i++)
|
||||
{
|
||||
T t;
|
||||
json_str.push_back('{');
|
||||
const acl::db_row* row = (*this)[i];
|
||||
for_each(t, [&](auto& item, size_t I, bool is_last)
|
||||
{
|
||||
const char * row_name = get_name<T>(I);
|
||||
const char * value = (*row)[row_name];
|
||||
json_str.append(row_name);
|
||||
json_str.append(":");
|
||||
append_x(item, json_str);
|
||||
if (value)
|
||||
json_str.append(value);
|
||||
append_x(item, json_str);
|
||||
if (!is_last)
|
||||
json_str.push_back(',');
|
||||
|
||||
});
|
||||
json_str.push_back('}');
|
||||
json_str.push_back(',');
|
||||
}
|
||||
if (json_str.back() == ',')
|
||||
json_str.pop_back();
|
||||
json_str.push_back(']');
|
||||
return true;
|
||||
}
|
||||
template<typename T>
|
||||
bool insert(T &obj)
|
||||
{
|
||||
std::shared_ptr<acl::query> query = make_insert_query(obj);
|
||||
if (!exec_update(*query.get()))
|
||||
{
|
||||
std::cout << query->to_string().c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
template<typename T>
|
||||
std::shared_ptr<acl::query> make_insert_query(T &obj)
|
||||
{
|
||||
std::string sql_template("insert into ");
|
||||
sql_template.append(get_name<T>());
|
||||
sql_template.push_back('(');
|
||||
for_each(obj, [&sql_template](auto &item, size_t I, bool is_last) {
|
||||
sql_template.append(get_name<T>(I));
|
||||
if (!is_last)
|
||||
sql_template.push_back(',');
|
||||
});
|
||||
sql_template.append(")values(");
|
||||
|
||||
for_each(obj, [&sql_template](auto &item, size_t I, bool is_last) {
|
||||
|
||||
sql_template.push_back(':');
|
||||
sql_template.append(get_name<T>(I));
|
||||
if (!is_last)
|
||||
sql_template.push_back(',');
|
||||
});
|
||||
sql_template.push_back(')');
|
||||
|
||||
std::shared_ptr<acl::query> query(new acl::query);
|
||||
query->create_sql(sql_template.c_str());
|
||||
|
||||
for_each(obj, [&](auto &item, size_t I, bool is_last) {
|
||||
query->set_parameter(get_name<T>(I), item);
|
||||
});
|
||||
|
||||
return query;
|
||||
}
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value>
|
||||
append_x(T &, std::string &str)
|
||||
{
|
||||
return;
|
||||
}
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_arithmetic<T>::value>
|
||||
append_x(T &, std::string &str)
|
||||
{
|
||||
str.push_back('"');
|
||||
}
|
||||
void assign(int &item, const char *value)
|
||||
{
|
||||
item = std::strtol(value, 0, 10);
|
||||
}
|
||||
void assign(unsigned int &item, const char *value)
|
||||
{
|
||||
item = std::strtoul(value, 0, 10);
|
||||
}
|
||||
void assign(float &item, const char *value)
|
||||
{
|
||||
item = std::strtof(value, 0);
|
||||
}
|
||||
|
||||
void assign(double &item, const char *value)
|
||||
{
|
||||
item = std::strtod(value, 0);
|
||||
}
|
||||
|
||||
void assign(acl::string &item, const char *value)
|
||||
{
|
||||
item.append(value);
|
||||
}
|
||||
|
||||
void assign(std::string &item, const char *value)
|
||||
{
|
||||
item.append(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
503
lib_acl_cpp1z/include/lib_acl_cpp1z/reflection/reflection.hpp
Normal file
503
lib_acl_cpp1z/include/lib_acl_cpp1z/reflection/reflection.hpp
Normal file
@ -0,0 +1,503 @@
|
||||
//
|
||||
// Created by QY on 2016-12-20.
|
||||
//
|
||||
|
||||
#ifndef UNTITLED3_REFLECTION_HPP
|
||||
#define UNTITLED3_REFLECTION_HPP
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
/******************************************/
|
||||
/* arg list expand macro, now support 120 args */
|
||||
#define MAKE_ARG_LIST_1(op, arg, ...) op(arg)
|
||||
#define MAKE_ARG_LIST_2(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_1(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_3(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_2(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_4(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_3(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_5(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_4(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_6(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_5(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_7(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_6(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_8(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_7(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_9(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_8(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_10(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_9(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_11(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_10(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_12(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_11(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_13(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_12(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_14(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_13(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_15(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_14(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_16(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_15(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_17(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_16(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_18(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_17(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_19(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_18(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_20(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_19(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_21(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_20(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_22(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_21(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_23(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_22(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_24(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_23(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_25(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_24(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_26(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_25(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_27(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_26(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_28(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_27(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_29(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_28(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_30(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_29(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_31(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_30(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_32(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_31(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_33(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_32(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_34(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_33(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_35(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_34(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_36(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_35(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_37(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_36(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_38(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_37(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_39(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_38(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_40(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_39(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_41(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_40(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_42(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_41(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_43(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_42(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_44(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_43(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_45(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_44(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_46(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_45(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_47(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_46(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_48(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_47(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_49(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_48(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_50(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_49(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_51(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_50(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_52(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_51(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_53(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_52(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_54(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_53(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_55(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_54(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_56(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_55(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_57(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_56(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_58(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_57(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_59(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_58(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_60(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_59(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_61(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_60(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_62(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_61(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_63(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_62(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_64(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_63(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_65(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_64(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_66(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_65(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_67(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_66(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_68(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_67(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_69(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_68(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_70(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_69(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_71(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_70(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_72(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_71(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_73(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_72(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_74(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_73(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_75(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_74(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_76(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_75(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_77(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_76(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_78(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_77(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_79(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_78(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_80(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_79(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_81(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_80(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_82(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_81(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_83(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_82(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_84(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_83(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_85(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_84(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_86(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_85(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_87(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_86(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_88(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_87(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_89(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_88(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_90(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_89(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_91(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_90(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_92(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_91(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_93(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_92(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_94(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_93(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_95(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_94(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_96(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_95(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_97(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_96(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_98(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_97(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_99(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_98(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_100(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_99(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_101(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_100(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_102(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_101(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_103(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_102(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_104(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_103(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_105(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_104(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_106(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_105(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_107(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_106(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_108(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_107(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_109(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_108(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_110(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_109(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_111(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_110(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_112(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_111(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_113(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_112(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_114(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_113(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_115(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_114(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_116(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_115(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_117(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_116(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_118(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_117(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_119(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_118(op, __VA_ARGS__))
|
||||
#define MAKE_ARG_LIST_120(op, arg, ...) op(arg), MARCO_EXPAND(MAKE_ARG_LIST_119(op, __VA_ARGS__))
|
||||
|
||||
#define SEPERATOR ,
|
||||
#define CON_STR_1(element, ...) #element
|
||||
#define CON_STR_2(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_1(__VA_ARGS__))
|
||||
#define CON_STR_3(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_2(__VA_ARGS__))
|
||||
#define CON_STR_4(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_3(__VA_ARGS__))
|
||||
#define CON_STR_5(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_4(__VA_ARGS__))
|
||||
#define CON_STR_6(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_5(__VA_ARGS__))
|
||||
#define CON_STR_7(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_6(__VA_ARGS__))
|
||||
#define CON_STR_8(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_7(__VA_ARGS__))
|
||||
#define CON_STR_9(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_8(__VA_ARGS__))
|
||||
#define CON_STR_10(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_9(__VA_ARGS__))
|
||||
#define CON_STR_11(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_10(__VA_ARGS__))
|
||||
#define CON_STR_12(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_11(__VA_ARGS__))
|
||||
#define CON_STR_13(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_12(__VA_ARGS__))
|
||||
#define CON_STR_14(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_13(__VA_ARGS__))
|
||||
#define CON_STR_15(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_14(__VA_ARGS__))
|
||||
#define CON_STR_16(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_15(__VA_ARGS__))
|
||||
#define CON_STR_17(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_16(__VA_ARGS__))
|
||||
#define CON_STR_18(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_17(__VA_ARGS__))
|
||||
#define CON_STR_19(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_18(__VA_ARGS__))
|
||||
#define CON_STR_20(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_19(__VA_ARGS__))
|
||||
#define CON_STR_21(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_20(__VA_ARGS__))
|
||||
#define CON_STR_22(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_21(__VA_ARGS__))
|
||||
#define CON_STR_23(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_22(__VA_ARGS__))
|
||||
#define CON_STR_24(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_23(__VA_ARGS__))
|
||||
#define CON_STR_25(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_24(__VA_ARGS__))
|
||||
#define CON_STR_26(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_25(__VA_ARGS__))
|
||||
#define CON_STR_27(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_26(__VA_ARGS__))
|
||||
#define CON_STR_28(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_27(__VA_ARGS__))
|
||||
#define CON_STR_29(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_28(__VA_ARGS__))
|
||||
#define CON_STR_30(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_29(__VA_ARGS__))
|
||||
#define CON_STR_31(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_30(__VA_ARGS__))
|
||||
#define CON_STR_32(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_31(__VA_ARGS__))
|
||||
#define CON_STR_33(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_32(__VA_ARGS__))
|
||||
#define CON_STR_34(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_33(__VA_ARGS__))
|
||||
#define CON_STR_35(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_34(__VA_ARGS__))
|
||||
#define CON_STR_36(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_35(__VA_ARGS__))
|
||||
#define CON_STR_37(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_36(__VA_ARGS__))
|
||||
#define CON_STR_38(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_37(__VA_ARGS__))
|
||||
#define CON_STR_39(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_38(__VA_ARGS__))
|
||||
#define CON_STR_40(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_39(__VA_ARGS__))
|
||||
#define CON_STR_41(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_40(__VA_ARGS__))
|
||||
#define CON_STR_42(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_41(__VA_ARGS__))
|
||||
#define CON_STR_43(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_42(__VA_ARGS__))
|
||||
#define CON_STR_44(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_43(__VA_ARGS__))
|
||||
#define CON_STR_45(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_44(__VA_ARGS__))
|
||||
#define CON_STR_46(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_45(__VA_ARGS__))
|
||||
#define CON_STR_47(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_46(__VA_ARGS__))
|
||||
#define CON_STR_48(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_47(__VA_ARGS__))
|
||||
#define CON_STR_49(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_48(__VA_ARGS__))
|
||||
#define CON_STR_50(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_49(__VA_ARGS__))
|
||||
#define CON_STR_51(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_50(__VA_ARGS__))
|
||||
#define CON_STR_52(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_51(__VA_ARGS__))
|
||||
#define CON_STR_53(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_52(__VA_ARGS__))
|
||||
#define CON_STR_54(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_53(__VA_ARGS__))
|
||||
#define CON_STR_55(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_54(__VA_ARGS__))
|
||||
#define CON_STR_56(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_55(__VA_ARGS__))
|
||||
#define CON_STR_57(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_56(__VA_ARGS__))
|
||||
#define CON_STR_58(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_57(__VA_ARGS__))
|
||||
#define CON_STR_59(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_58(__VA_ARGS__))
|
||||
#define CON_STR_60(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_59(__VA_ARGS__))
|
||||
#define CON_STR_61(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_60(__VA_ARGS__))
|
||||
#define CON_STR_62(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_61(__VA_ARGS__))
|
||||
#define CON_STR_63(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_62(__VA_ARGS__))
|
||||
#define CON_STR_64(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_63(__VA_ARGS__))
|
||||
#define CON_STR_65(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_64(__VA_ARGS__))
|
||||
#define CON_STR_66(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_65(__VA_ARGS__))
|
||||
#define CON_STR_67(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_66(__VA_ARGS__))
|
||||
#define CON_STR_68(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_67(__VA_ARGS__))
|
||||
#define CON_STR_69(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_68(__VA_ARGS__))
|
||||
#define CON_STR_70(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_69(__VA_ARGS__))
|
||||
#define CON_STR_71(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_70(__VA_ARGS__))
|
||||
#define CON_STR_72(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_71(__VA_ARGS__))
|
||||
#define CON_STR_73(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_72(__VA_ARGS__))
|
||||
#define CON_STR_74(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_73(__VA_ARGS__))
|
||||
#define CON_STR_75(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_74(__VA_ARGS__))
|
||||
#define CON_STR_76(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_75(__VA_ARGS__))
|
||||
#define CON_STR_77(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_76(__VA_ARGS__))
|
||||
#define CON_STR_78(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_77(__VA_ARGS__))
|
||||
#define CON_STR_79(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_78(__VA_ARGS__))
|
||||
#define CON_STR_80(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_79(__VA_ARGS__))
|
||||
#define CON_STR_81(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_80(__VA_ARGS__))
|
||||
#define CON_STR_82(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_81(__VA_ARGS__))
|
||||
#define CON_STR_83(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_82(__VA_ARGS__))
|
||||
#define CON_STR_84(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_83(__VA_ARGS__))
|
||||
#define CON_STR_85(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_84(__VA_ARGS__))
|
||||
#define CON_STR_86(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_85(__VA_ARGS__))
|
||||
#define CON_STR_87(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_86(__VA_ARGS__))
|
||||
#define CON_STR_88(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_87(__VA_ARGS__))
|
||||
#define CON_STR_89(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_88(__VA_ARGS__))
|
||||
#define CON_STR_90(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_89(__VA_ARGS__))
|
||||
#define CON_STR_91(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_90(__VA_ARGS__))
|
||||
#define CON_STR_92(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_91(__VA_ARGS__))
|
||||
#define CON_STR_93(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_92(__VA_ARGS__))
|
||||
#define CON_STR_94(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_93(__VA_ARGS__))
|
||||
#define CON_STR_95(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_94(__VA_ARGS__))
|
||||
#define CON_STR_96(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_95(__VA_ARGS__))
|
||||
#define CON_STR_97(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_96(__VA_ARGS__))
|
||||
#define CON_STR_98(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_97(__VA_ARGS__))
|
||||
#define CON_STR_99(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_98(__VA_ARGS__))
|
||||
#define CON_STR_100(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_99(__VA_ARGS__))
|
||||
#define CON_STR_101(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_100(__VA_ARGS__))
|
||||
#define CON_STR_102(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_101(__VA_ARGS__))
|
||||
#define CON_STR_103(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_102(__VA_ARGS__))
|
||||
#define CON_STR_104(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_103(__VA_ARGS__))
|
||||
#define CON_STR_105(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_104(__VA_ARGS__))
|
||||
#define CON_STR_106(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_105(__VA_ARGS__))
|
||||
#define CON_STR_107(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_106(__VA_ARGS__))
|
||||
#define CON_STR_108(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_107(__VA_ARGS__))
|
||||
#define CON_STR_109(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_108(__VA_ARGS__))
|
||||
#define CON_STR_110(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_109(__VA_ARGS__))
|
||||
#define CON_STR_111(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_110(__VA_ARGS__))
|
||||
#define CON_STR_112(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_111(__VA_ARGS__))
|
||||
#define CON_STR_113(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_112(__VA_ARGS__))
|
||||
#define CON_STR_114(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_113(__VA_ARGS__))
|
||||
#define CON_STR_115(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_114(__VA_ARGS__))
|
||||
#define CON_STR_116(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_115(__VA_ARGS__))
|
||||
#define CON_STR_117(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_116(__VA_ARGS__))
|
||||
#define CON_STR_118(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_117(__VA_ARGS__))
|
||||
#define CON_STR_119(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_118(__VA_ARGS__))
|
||||
#define CON_STR_120(element, ...) #element SEPERATOR MARCO_EXPAND(CON_STR_119(__VA_ARGS__))
|
||||
#define RSEQ_N() \
|
||||
119,118,117,116,115,114,113,112,111,110,\
|
||||
109,108,107,106,105,104,103,102,101,100,\
|
||||
99,98,97,96,95,94,93,92,91,90, \
|
||||
89,88,87,86,85,84,83,82,81,80, \
|
||||
79,78,77,76,75,74,73,72,71,70, \
|
||||
69,68,67,66,65,64,63,62,61,60, \
|
||||
59,58,57,56,55,54,53,52,51,50, \
|
||||
49,48,47,46,45,44,43,42,41,40, \
|
||||
39,38,37,36,35,34,33,32,31,30, \
|
||||
29,28,27,26,25,24,23,22,21,20, \
|
||||
19,18,17,16,15,14,13,12,11,10, \
|
||||
9,8,7,6,5,4,3,2,1,0
|
||||
|
||||
#define ARG_N( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
|
||||
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
|
||||
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
|
||||
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
|
||||
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
|
||||
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
|
||||
_61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \
|
||||
_71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \
|
||||
_81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \
|
||||
_91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \
|
||||
_101,_102,_103,_104,_105,_106,_107,_108,_109,_110, \
|
||||
_111,_112,_113,_114,_115,_116,_117,_118,_119,N, ...) N
|
||||
|
||||
#define MARCO_EXPAND(...) __VA_ARGS__
|
||||
#define APPLY_VARIADIC_MACRO(macro, ...) MARCO_EXPAND(macro(__VA_ARGS__))
|
||||
|
||||
#define ADD_REFERENCE(t) std::reference_wrapper<decltype(t)>(t)
|
||||
#define ADD_REFERENCE_CONST(t) std::reference_wrapper<std::add_const_t<decltype(t)>>(t)
|
||||
#define OBJECT(t) t//std::make_pair(#t, ADD_REFERENCE(t))
|
||||
//#define OBJECT_CONST(t) std::make_pair(#t, ADD_REFERENCE_CONST(t))
|
||||
#define MAKE_NAMES(...) #__VA_ARGS__,
|
||||
|
||||
//#define MAKE_TUPLE_CONST(...) auto tuple() const { return std::make_tuple(__VA_ARGS__); }
|
||||
|
||||
//note use MACRO_CONCAT like A##_##B direct may cause marco expand error
|
||||
#define MACRO_CONCAT(A, B) MACRO_CONCAT1(A, B)
|
||||
#define MACRO_CONCAT1(A, B) A##_##B
|
||||
|
||||
#define MAKE_ARG_LIST(N, op, arg, ...) \
|
||||
MACRO_CONCAT(MAKE_ARG_LIST, N)(op, arg, __VA_ARGS__)
|
||||
|
||||
#define GET_ARG_COUNT_INNER(...) MARCO_EXPAND(ARG_N(__VA_ARGS__))
|
||||
#define GET_ARG_COUNT(...) GET_ARG_COUNT_INNER(__VA_ARGS__, RSEQ_N())
|
||||
|
||||
#define MAKE_STR_LIST(...) \
|
||||
MACRO_CONCAT(CON_STR, GET_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
template<typename...> using void_t = void;
|
||||
|
||||
template<typename> struct Members {};
|
||||
|
||||
#define MAKE_META_DATA_IMPL(STRUCT_NAME, ...)\
|
||||
template<>struct Members<STRUCT_NAME>{\
|
||||
constexpr decltype(auto) static apply(){\
|
||||
return std::make_tuple(__VA_ARGS__);\
|
||||
}\
|
||||
using type = void;\
|
||||
constexpr static const char *name = #STRUCT_NAME;\
|
||||
constexpr static const size_t value = GET_ARG_COUNT(__VA_ARGS__);\
|
||||
constexpr static const std::array<const char*, value>& arr = arr_##STRUCT_NAME;\
|
||||
};
|
||||
|
||||
#define MAKE_META_DATA(STRUCT_NAME, N, ...) \
|
||||
constexpr std::array<const char*, N> arr_##STRUCT_NAME = {MARCO_EXPAND(MACRO_CONCAT(CON_STR, N)(__VA_ARGS__))};\
|
||||
MAKE_META_DATA_IMPL(STRUCT_NAME, MAKE_ARG_LIST(N, &STRUCT_NAME::OBJECT, __VA_ARGS__))
|
||||
|
||||
//MAKE_TUPLE_CONST(MAKE_ARG_LIST(N, OBJECT, __VA_ARGS__))
|
||||
|
||||
#define REFLECTION(STRUCT_NAME, ...) \
|
||||
MAKE_META_DATA(STRUCT_NAME, GET_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct is_reflection : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
// this way of using SFINEA is type reference and cv qualifiers immuned
|
||||
template <typename T>
|
||||
struct is_reflection<T, void_t<
|
||||
typename Members<std::remove_const_t <std::remove_reference_t<T>>>::type
|
||||
>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
//template<size_t I, typename F, typename T>
|
||||
//std::enable_if_t<is_reflection<T>::value> apply_value(F&& f, T&& t, bool is_last);
|
||||
|
||||
template<size_t I, typename F, typename T>
|
||||
void apply_value(F&& f, T&& t, bool is_last)
|
||||
{
|
||||
std::forward<F>(f)(std::forward<T>(t), I, is_last);
|
||||
};
|
||||
|
||||
//template<size_t I, typename F, typename T>
|
||||
//constexpr void for_each_impl(F&&, T&&, bool is_last, void_t<typename Members<std::remove_const_t <std::remove_reference_t<T>>>::type> *);
|
||||
|
||||
//template<size_t I, typename F, typename T>
|
||||
//constexpr void for_each_impl(F&& f, T&& t, bool is_last, ...)
|
||||
//{
|
||||
// std::forward<F>(f)(std::forward<T>(t), I, is_last);
|
||||
// //render_json_value<I>(std::forward<F>(f), std::forward<T>(t), is_last);
|
||||
//}
|
||||
|
||||
template<size_t I, typename F, typename T>
|
||||
constexpr void for_each_impl(F&& f, T&&t, bool is_last, void_t<typename Members<std::remove_const_t <std::remove_reference_t<T>>>::type> *)
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
apply(std::forward<F>(f), std::forward<T>(t), M::apply(), std::make_index_sequence<M::value>{});
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------------------------------------//
|
||||
template<size_t I, typename F, typename F1, typename T>
|
||||
std::enable_if_t<is_reflection<T>::value> apply_value(F&& f, F1&& f1, T&& t, bool is_last)
|
||||
{
|
||||
std::forward<F1>(f1)(std::forward<T>(t), I, is_last);
|
||||
}
|
||||
|
||||
template<size_t I, typename F, typename F1, typename T>
|
||||
std::enable_if_t<!is_reflection<T>::value> apply_value(F&& f, F1&& f1, T&& t, bool is_last)
|
||||
{
|
||||
std::forward<F>(f)(std::forward<T>(t), I, is_last);
|
||||
}
|
||||
|
||||
//template<size_t I, typename F, typename F1, typename T>
|
||||
//constexpr void for_each_impl(F&&, F1&&, T&&, bool is_last, void_t<typename Members<std::remove_const_t <std::remove_reference_t<T>>>::type> *);
|
||||
|
||||
template<size_t I, typename F, typename F1, typename T>
|
||||
constexpr void for_each_impl(F&& f, F1&& f1, T&&t, bool is_last, void_t<typename Members<std::remove_const_t <std::remove_reference_t<T>>>::type> *)
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
apply(std::forward<F>(f), std::forward<F1>(f1), std::forward<T>(t), M::apply(), std::make_index_sequence<M::value>{});
|
||||
}
|
||||
|
||||
template<typename F, typename F1, typename T, typename... Rest,std::size_t I0, std::size_t... I>
|
||||
constexpr void apply(F&& f, F1&& f1, T&&t, std::tuple<Rest...>&& tp, std::index_sequence<I0, I...>)
|
||||
{
|
||||
apply_value<I0>(std::forward<F>(f), std::forward<F1>(f1), std::forward<T>(t).*(std::get<I0>(tp)), sizeof...(I)==0);
|
||||
apply(std::forward<F>(f), std::forward<F1>(f1), std::forward<T>(t), (std::tuple<Rest...>&&)tp, std::index_sequence<I...>{});
|
||||
}
|
||||
|
||||
template<typename F, typename F1, typename T,typename... Rest>
|
||||
constexpr void apply(F&& f, F1&&, T&& t, std::tuple<Rest...>&&, std::index_sequence<>)
|
||||
{
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------------------------------------//
|
||||
|
||||
template<typename F, typename T, typename... Rest,std::size_t I0, std::size_t... I>
|
||||
constexpr void apply(F&& f, T&&t, std::tuple<Rest...>&& tp, std::index_sequence<I0, I...>)
|
||||
{
|
||||
apply_value<I0>(std::forward<F>(f), std::forward<T>(t).*(std::get<I0>(tp)), sizeof...(I)==0);
|
||||
//for_each_impl<I0>(std::forward<F>(f), std::forward<T>(t).*(std::get<I0>(tp)), sizeof...(I)==0, (void *)nullptr);
|
||||
apply(std::forward<F>(f), std::forward<T>(t), (std::tuple<Rest...>&&)tp, std::index_sequence<I...>{});
|
||||
}
|
||||
|
||||
template<typename F, typename T,typename... Rest>
|
||||
constexpr void apply(F&& f, T&& t, std::tuple<Rest...>&&, std::index_sequence<>)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename F, typename... Rest,std::size_t I0, std::size_t... I>
|
||||
constexpr void apply_tuple(F&& f, std::tuple<Rest...>& tp, std::index_sequence<I0, I...>)
|
||||
{
|
||||
apply_value<I0>(std::forward<F>(f), std::get<I0>(tp), sizeof...(I)==0);
|
||||
apply_tuple(std::forward<F>(f), tp, std::index_sequence<I...>{});
|
||||
}
|
||||
|
||||
template<typename F, typename... Rest>
|
||||
constexpr void apply_tuple(F&& f, std::tuple<Rest...>&, std::index_sequence<>)
|
||||
{
|
||||
}
|
||||
|
||||
template<size_t I, typename T>
|
||||
constexpr decltype(auto) get(T&& t)
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
return std::forward<T>(t).*(std::get<I>(M::apply()));
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
constexpr std::enable_if_t<is_reflection<T>::value> for_each(T&& t, F&& f)
|
||||
{
|
||||
for_each_impl<0>(std::forward<F>(f), std::forward<T>(t), false, (void *)nullptr);
|
||||
}
|
||||
|
||||
template<typename T, typename F, typename F1>
|
||||
constexpr std::enable_if_t<is_reflection<T>::value> for_each(T&& t, F&& f, F1&& f1)
|
||||
{
|
||||
for_each_impl<0>(std::forward<F>(f), std::forward<F1>(f1), std::forward<T>(t), false, (void *)nullptr);
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
constexpr std::enable_if_t<!is_reflection<T>::value> for_each(T&& tp, F&& f)
|
||||
{
|
||||
apply_tuple(std::forward<F>(f), std::forward<T>(tp), std::make_index_sequence<std::tuple_size<std::remove_reference_t <T>>::value>{});
|
||||
}
|
||||
|
||||
template<typename T, size_t I>
|
||||
constexpr const char* get_name()
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
static_assert(I<M::value, "out of range");
|
||||
return M::arr[I];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const char* get_name()
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
return M::name;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const char* get_name(size_t i)
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
//if(i>=M::value)
|
||||
// return "";
|
||||
|
||||
return i >= M::value?"":M::arr[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<is_reflection<T>::value, size_t> get_value()
|
||||
{
|
||||
using M = Members<std::remove_const_t <std::remove_reference_t<T>>>;
|
||||
return M::value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!is_reflection<T>::value, size_t> get_value()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif //UNTITLED3_REFLECTION_HPP
|
95
lib_acl_cpp1z/samples/db/query/main.cpp
Normal file
95
lib_acl_cpp1z/samples/db/query/main.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
#include "lib_acl_cpp1z/db/db_mysql.hpp"
|
||||
|
||||
|
||||
struct group_tbl
|
||||
{
|
||||
std::string group_name;
|
||||
std::string uvip_tbl;
|
||||
std::string access_tbl;
|
||||
std::string access_week_tbl;
|
||||
std::string access_month_tbl;
|
||||
std::string update_date;
|
||||
int disable;
|
||||
int add_by_hand;
|
||||
int class_level;
|
||||
|
||||
|
||||
};
|
||||
REFLECTION(
|
||||
group_tbl,
|
||||
group_name,
|
||||
uvip_tbl,
|
||||
access_tbl,
|
||||
access_week_tbl,
|
||||
access_month_tbl,
|
||||
update_date,
|
||||
disable,
|
||||
add_by_hand,
|
||||
class_level);
|
||||
|
||||
void select_as_json(acl::lz::db_mysql &db, int n)
|
||||
{
|
||||
acl::query query;
|
||||
query.create_sql("select * from group_tbl where group_name=:group"
|
||||
" and uvip_tbl=:test")
|
||||
.set_format("group", "group:%d", n)
|
||||
.set_format("test", "test");
|
||||
|
||||
std::string json_str;
|
||||
if (db.select<group_tbl>(query.to_string().c_str(), json_str))
|
||||
std::cout << json_str << std::endl;
|
||||
}
|
||||
|
||||
void select_as_obj(acl::lz::db_mysql &db, int n)
|
||||
{
|
||||
acl::query query;
|
||||
query.create_sql("select * from group_tbl where group_name=:group"
|
||||
" and uvip_tbl=:test")
|
||||
.set_format("group", "group:%d", n)
|
||||
.set_format("test", "test");
|
||||
|
||||
if (db.select<group_tbl>(query.to_string().c_str()).first)
|
||||
std::cout << "select ok" << std::endl;
|
||||
else
|
||||
std::cout << "select error" << std::endl;;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
acl::string path("F:\\fork\\acl-dev\\acl\\libmysql.dll");
|
||||
acl::db_handle::set_loadpath(path);
|
||||
|
||||
acl::string dbaddr("192.168.3.170:3306");
|
||||
acl::string dbname("acl_db"), dbuser("root"), dbpass("skyinno251");
|
||||
int max = 200;
|
||||
acl::lz::db_mysql db(dbaddr, dbname, dbuser, dbpass, 0, false);
|
||||
|
||||
if (db.open() == false)
|
||||
{
|
||||
printf("open db(%s@%s) error\r\n",
|
||||
dbaddr.c_str(), dbname.c_str());
|
||||
getchar();
|
||||
return 1;
|
||||
}
|
||||
|
||||
group_tbl group_tbl_;
|
||||
group_tbl_.access_month_tbl = "access_month_tbl11";
|
||||
group_tbl_.access_tbl = "access_tbl 111";
|
||||
group_tbl_.access_week_tbl = "hello world";
|
||||
group_tbl_.add_by_hand = 1;
|
||||
group_tbl_.class_level = 1;
|
||||
group_tbl_.disable = 0;
|
||||
group_tbl_.group_name = "group_name";
|
||||
group_tbl_.update_date = "2017-03-14 09:55:00";
|
||||
group_tbl_.uvip_tbl = "uvip_tbl 1";
|
||||
|
||||
db.insert(group_tbl_);
|
||||
|
||||
for (size_t i = 0; i < max; i++)
|
||||
{
|
||||
select_as_json(db, i);
|
||||
select_as_obj(db, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
138
lib_acl_cpp1z/samples/db/query/query.vcxproj
Normal file
138
lib_acl_cpp1z/samples/db/query/query.vcxproj
Normal file
@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{01C149B2-9F60-479F-A9E1-D7799578D793}</ProjectGuid>
|
||||
<RootNamespace>query</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)lib_acl_cpp\include;$(SolutionDir)lib_acl_cpp1z\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_vc2015d.lib;lib_acl_cpp_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib_acl_cpp;$(SolutionDir)lib_acl;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)lib_acl_cpp\include;$(SolutionDir)lib_acl_cpp1z\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>lib_acl_vc2015d.lib;lib_acl_cpp_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib_acl_cpp;$(SolutionDir)lib_acl;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)lib_acl_cpp\include;$(SolutionDir)lib_acl_cpp1z\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lib_acl_vc2015d.lib;lib_acl_cpp_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib_acl_cpp;$(SolutionDir)lib_acl;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)lib_acl_cpp\include;$(SolutionDir)lib_acl_cpp1z\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lib_acl_vc2015d.lib;lib_acl_cpp_vc2015d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)lib_acl_cpp;$(SolutionDir)lib_acl;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
lib_acl_cpp1z/samples/db/query/query.vcxproj.filters
Normal file
22
lib_acl_cpp1z/samples/db/query/query.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user