Merge pull request #1 from acl-dev/master

merge
This commit is contained in:
郑树新 2017-05-31 12:52:29 +08:00 committed by GitHub
commit 6e8c263024
29 changed files with 2291 additions and 523 deletions

View File

@ -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)
{

View File

@ -12,4 +12,3 @@
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "lib_protocol.h"

View File

@ -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*}

View File

@ -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

View 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_;
};
}

View File

@ -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();

View 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

View 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
}

View File

@ -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;
}

View File

@ -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_;
};

View 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;
}

View 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;
}

View 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();
};

View File

@ -0,0 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// master_threads.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用

View 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

View File

@ -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>

View File

@ -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>

View 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>

View File

@ -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;
}

View File

@ -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_;
};

View File

@ -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);

View 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()
{
}
}

View File

@ -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

View File

@ -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;

View 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);
}
};
}
}

View 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

View 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;
}

View 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>

View 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>