initial commit
This commit is contained in:
66
third_party/libhv/cpputil/RAII.cpp
vendored
Executable file
66
third_party/libhv/cpputil/RAII.cpp
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
#include "hplatform.h"
|
||||
|
||||
#ifdef OS_WIN
|
||||
#ifdef ENABLE_WINDUMP
|
||||
#include <dbghelp.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib,"dbghelp.lib")
|
||||
#endif
|
||||
static LONG UnhandledException(EXCEPTION_POINTERS *pException) {
|
||||
char modulefile[256];
|
||||
GetModuleFileName(NULL, modulefile, sizeof(modulefile));
|
||||
char* pos = strrchr(modulefile, '\\');
|
||||
char* modulefilename = pos + 1;
|
||||
SYSTEMTIME st;
|
||||
GetLocalTime(&st);
|
||||
char filename[256];
|
||||
snprintf(filename, sizeof(filename), "core_%s_%04d%02d%02d_%02d%02d%02d_%03d.dump",
|
||||
modulefilename,
|
||||
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||
HANDLE hDumpFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
|
||||
dumpInfo.ExceptionPointers = pException;
|
||||
dumpInfo.ThreadId = GetCurrentThreadId();
|
||||
dumpInfo.ClientPointers = TRUE;
|
||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
|
||||
CloseHandle(hDumpFile);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "hsocket.h"
|
||||
class WsaRAII {
|
||||
public:
|
||||
WsaRAII() {
|
||||
WSAInit();
|
||||
#ifdef ENABLE_WINDUMP
|
||||
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)UnhandledException);
|
||||
#endif
|
||||
}
|
||||
~WsaRAII() {
|
||||
WSADeinit();
|
||||
}
|
||||
};
|
||||
static WsaRAII s_wsa;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CURL
|
||||
#include "curl/curl.h"
|
||||
#ifdef _MSC_VER
|
||||
//#pragma comment(lib, "libcurl.a")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#pragma comment(lib, "wldap32.lib")
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#endif
|
||||
class CurlRAII {
|
||||
public:
|
||||
CurlRAII() {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
}
|
||||
~CurlRAII() {
|
||||
curl_global_cleanup();
|
||||
}
|
||||
};
|
||||
static CurlRAII s_curl;
|
||||
#endif
|
||||
20
third_party/libhv/cpputil/README.md
vendored
Executable file
20
third_party/libhv/cpputil/README.md
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
.
|
||||
├── hasync.h hv::async实现
|
||||
├── hdir.h 目录(ls实现)
|
||||
├── hfile.h 文件类
|
||||
├── hobjectpool.h 对象池
|
||||
├── hpath.h 路径操作
|
||||
├── hscope.h 作用域模板类
|
||||
├── hstring.h 字符串操作
|
||||
├── hthreadpool.h 线程池
|
||||
├── hurl.h URL操作
|
||||
├── ifconfig.h 网络配置(ifconfig实现)
|
||||
├── iniparser.h INI解析
|
||||
├── json.hpp JSON解析
|
||||
├── singleton.h 单例模式宏
|
||||
└── ThreadLocalStorage.h 线程本地存储类
|
||||
|
||||
```
|
||||
32
third_party/libhv/cpputil/ThreadLocalStorage.cpp
vendored
Executable file
32
third_party/libhv/cpputil/ThreadLocalStorage.cpp
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
#include "ThreadLocalStorage.h"
|
||||
|
||||
#include "hthread.h"
|
||||
|
||||
namespace hv {
|
||||
|
||||
ThreadLocalStorage ThreadLocalStorage::tls[ThreadLocalStorage::MAX_NUM];
|
||||
|
||||
void ThreadLocalStorage::set(int idx, void* val) {
|
||||
return tls[idx].set(val);
|
||||
}
|
||||
|
||||
void* ThreadLocalStorage::get(int idx) {
|
||||
return tls[idx].get();
|
||||
}
|
||||
|
||||
void ThreadLocalStorage::setThreadName(const char* name) {
|
||||
set(THREAD_NAME, (void*)name);
|
||||
}
|
||||
|
||||
const char* ThreadLocalStorage::threadName() {
|
||||
void* value = get(THREAD_NAME);
|
||||
if (value) {
|
||||
return (char*)value;
|
||||
}
|
||||
|
||||
static char unnamed[32] = {0};
|
||||
snprintf(unnamed, sizeof(unnamed)-1, "thread-%ld", hv_gettid());
|
||||
return unnamed;
|
||||
}
|
||||
|
||||
}
|
||||
67
third_party/libhv/cpputil/ThreadLocalStorage.h
vendored
Executable file
67
third_party/libhv/cpputil/ThreadLocalStorage.h
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
#ifndef HV_THREAD_LOCAL_STORAGE_H_
|
||||
#define HV_THREAD_LOCAL_STORAGE_H_
|
||||
|
||||
#include "hexport.h"
|
||||
#include "hplatform.h"
|
||||
|
||||
#ifdef OS_WIN
|
||||
|
||||
#define hthread_key_t DWORD
|
||||
#define INVALID_HTHREAD_KEY 0xFFFFFFFF
|
||||
#define hthread_key_create(pkey) *pkey = TlsAlloc()
|
||||
#define hthread_key_delete TlsFree
|
||||
#define hthread_get_value TlsGetValue
|
||||
#define hthread_set_value TlsSetValue
|
||||
|
||||
#else
|
||||
|
||||
#define hthread_key_t pthread_key_t
|
||||
#define INVALID_HTHREAD_KEY 0xFFFFFFFF
|
||||
#define hthread_key_create(pkey) pthread_key_create(pkey, NULL)
|
||||
#define hthread_key_delete pthread_key_delete
|
||||
#define hthread_get_value pthread_getspecific
|
||||
#define hthread_set_value pthread_setspecific
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace hv {
|
||||
|
||||
class HV_EXPORT ThreadLocalStorage {
|
||||
public:
|
||||
enum {
|
||||
THREAD_NAME = 0,
|
||||
EVENT_LOOP = 1,
|
||||
MAX_NUM = 16,
|
||||
};
|
||||
ThreadLocalStorage() {
|
||||
hthread_key_create(&key);
|
||||
}
|
||||
|
||||
~ThreadLocalStorage() {
|
||||
hthread_key_delete(key);
|
||||
}
|
||||
|
||||
void set(void* val) {
|
||||
hthread_set_value(key, val);
|
||||
}
|
||||
|
||||
void* get() {
|
||||
return hthread_get_value(key);
|
||||
}
|
||||
|
||||
static void set(int idx, void* val);
|
||||
static void* get(int idx);
|
||||
|
||||
static void setThreadName(const char* name);
|
||||
static const char* threadName();
|
||||
|
||||
private:
|
||||
hthread_key_t key;
|
||||
static ThreadLocalStorage tls[MAX_NUM];
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HV_THREAD_LOCAL_STORAGE_H_
|
||||
7
third_party/libhv/cpputil/hasync.cpp
vendored
Executable file
7
third_party/libhv/cpputil/hasync.cpp
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#include "hasync.h"
|
||||
|
||||
namespace hv {
|
||||
|
||||
SINGLETON_IMPL(GlobalThreadPool)
|
||||
|
||||
}
|
||||
49
third_party/libhv/cpputil/hasync.h
vendored
Executable file
49
third_party/libhv/cpputil/hasync.h
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
#ifndef HV_ASYNC_H_
|
||||
#define HV_ASYNC_H_
|
||||
|
||||
#include "hexport.h"
|
||||
#include "hthreadpool.h"
|
||||
#include "singleton.h"
|
||||
|
||||
namespace hv {
|
||||
|
||||
class HV_EXPORT GlobalThreadPool : public HThreadPool {
|
||||
SINGLETON_DECL(GlobalThreadPool)
|
||||
protected:
|
||||
GlobalThreadPool() : HThreadPool() {}
|
||||
~GlobalThreadPool() {}
|
||||
};
|
||||
|
||||
/*
|
||||
* return a future, calling future.get() will wait task done and return RetType.
|
||||
* async(fn, args...)
|
||||
* async(std::bind(&Class::mem_fn, &obj))
|
||||
* async(std::mem_fn(&Class::mem_fn, &obj))
|
||||
*
|
||||
*/
|
||||
template<class Fn, class... Args>
|
||||
auto async(Fn&& fn, Args&&... args) -> std::future<decltype(fn(args...))> {
|
||||
return GlobalThreadPool::instance()->commit(std::forward<Fn>(fn), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
class async {
|
||||
public:
|
||||
static void startup(int min_threads = DEFAULT_THREAD_POOL_MIN_THREAD_NUM,
|
||||
int max_threads = DEFAULT_THREAD_POOL_MAX_THREAD_NUM,
|
||||
int max_idle_ms = DEFAULT_THREAD_POOL_MAX_IDLE_TIME) {
|
||||
GlobalThreadPool* gtp = GlobalThreadPool::instance();
|
||||
if (gtp->isStarted()) return;
|
||||
gtp->setMinThreadNum(min_threads);
|
||||
gtp->setMaxThreadNum(max_threads);
|
||||
gtp->setMaxIdleTime(max_idle_ms);
|
||||
gtp->start();
|
||||
}
|
||||
|
||||
static void cleanup() {
|
||||
GlobalThreadPool::exitInstance();
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace hv
|
||||
|
||||
#endif // HV_ASYNC_H_
|
||||
88
third_party/libhv/cpputil/hdir.cpp
vendored
Executable file
88
third_party/libhv/cpputil/hdir.cpp
vendored
Executable file
@@ -0,0 +1,88 @@
|
||||
#include "hdir.h"
|
||||
|
||||
#include "hplatform.h"
|
||||
|
||||
#ifdef OS_WIN
|
||||
//FILETIME starts from 1601-01-01 UTC, epoch from 1970-01-01 UTC
|
||||
//FILETIME unit (100ns)
|
||||
#define FILETIME_EPOCH_DIFF 11644473600 // s
|
||||
time_t FileTime2Epoch(FILETIME filetime) {
|
||||
uint64_t ll = (((uint64_t)filetime.dwHighDateTime) << 32) | filetime.dwLowDateTime;
|
||||
ll /= 1e7; // s
|
||||
return ll - FILETIME_EPOCH_DIFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool less(const hdir_t& lhs, const hdir_t& rhs) {
|
||||
return stricmp(lhs.name, rhs.name) < 0;
|
||||
}
|
||||
|
||||
int listdir(const char* dir, std::list<hdir_t>& dirs) {
|
||||
int dirlen = strlen(dir);
|
||||
if (dirlen > 256) {
|
||||
return -1;
|
||||
}
|
||||
char path[512];
|
||||
strcpy(path, dir);
|
||||
if (dir[dirlen-1] != '/') {
|
||||
strcat(path, "/");
|
||||
++dirlen;
|
||||
}
|
||||
dirs.clear();
|
||||
#ifdef OS_UNIX
|
||||
// opendir -> readdir -> closedir
|
||||
DIR* dp = opendir(dir);
|
||||
if (dp == NULL) return -1;
|
||||
struct dirent* result = NULL;
|
||||
struct stat st;
|
||||
hdir_t tmp;
|
||||
while ((result = readdir(dp))) {
|
||||
memset(&tmp, 0, sizeof(hdir_t));
|
||||
strncpy(tmp.name, result->d_name, sizeof(tmp.name));
|
||||
strncpy(path+dirlen, result->d_name, sizeof(path)-dirlen);
|
||||
if (lstat(path, &st) == 0) {
|
||||
if (S_ISREG(st.st_mode)) tmp.type = 'f';
|
||||
else if (S_ISDIR(st.st_mode)) tmp.type = 'd';
|
||||
else if (S_ISLNK(st.st_mode)) tmp.type = 'l';
|
||||
else if (S_ISBLK(st.st_mode)) tmp.type = 'b';
|
||||
else if (S_ISCHR(st.st_mode)) tmp.type = 'c';
|
||||
else if (S_ISSOCK(st.st_mode)) tmp.type = 's';
|
||||
else if (S_ISFIFO(st.st_mode)) tmp.type = 'p';
|
||||
else tmp.type = '-';
|
||||
tmp.mode = st.st_mode & 0777;
|
||||
tmp.size = st.st_size;
|
||||
tmp.atime = st.st_atime;
|
||||
tmp.mtime = st.st_mtime;
|
||||
tmp.ctime = st.st_ctime;
|
||||
}
|
||||
dirs.push_back(tmp);
|
||||
}
|
||||
closedir(dp);
|
||||
#elif defined(OS_WIN)
|
||||
// FindFirstFile -> FindNextFile -> FindClose
|
||||
strcat(path, "*");
|
||||
WIN32_FIND_DATAA data;
|
||||
HANDLE h = FindFirstFileA(path, &data);
|
||||
if (h == NULL) {
|
||||
return -1;
|
||||
}
|
||||
hdir_t tmp;
|
||||
do {
|
||||
memset(&tmp, 0, sizeof(hdir_t));
|
||||
strncpy(tmp.name, data.cFileName, sizeof(tmp.name));
|
||||
tmp.type = 'f';
|
||||
if (data.dwFileAttributes & _A_SUBDIR) {
|
||||
tmp.type = 'd';
|
||||
}
|
||||
tmp.mode = 0777;
|
||||
tmp.size = (((uint64_t)data.nFileSizeHigh) << 32) | data.nFileSizeLow;
|
||||
tmp.atime = FileTime2Epoch(data.ftLastAccessTime);
|
||||
tmp.mtime = FileTime2Epoch(data.ftLastWriteTime);
|
||||
tmp.ctime = FileTime2Epoch(data.ftCreationTime);
|
||||
dirs.push_back(tmp);
|
||||
} while (FindNextFileA(h, &data));
|
||||
FindClose(h);
|
||||
#endif
|
||||
dirs.sort(less);
|
||||
return dirs.size();
|
||||
}
|
||||
69
third_party/libhv/cpputil/hdir.h
vendored
Executable file
69
third_party/libhv/cpputil/hdir.h
vendored
Executable file
@@ -0,0 +1,69 @@
|
||||
#ifndef HV_DIR_H_
|
||||
#define HV_DIR_H_
|
||||
|
||||
/*
|
||||
*@code
|
||||
int main(int argc, char* argv[]) {
|
||||
const char* dir = ".";
|
||||
if (argc > 1) {
|
||||
dir = argv[1];
|
||||
}
|
||||
std::list<hdir_t> dirs;
|
||||
listdir(dir, dirs);
|
||||
for (auto& item : dirs) {
|
||||
printf("%c%c%c%c%c%c%c%c%c%c\t",
|
||||
item.type,
|
||||
item.mode & 0400 ? 'r' : '-',
|
||||
item.mode & 0200 ? 'w' : '-',
|
||||
item.mode & 0100 ? 'x' : '-',
|
||||
item.mode & 0040 ? 'r' : '-',
|
||||
item.mode & 0020 ? 'w' : '-',
|
||||
item.mode & 0010 ? 'x' : '-',
|
||||
item.mode & 0004 ? 'r' : '-',
|
||||
item.mode & 0002 ? 'w' : '-',
|
||||
item.mode & 0001 ? 'x' : '-');
|
||||
float hsize;
|
||||
if (item.size < 1024) {
|
||||
printf("%lu\t", item.size);
|
||||
}
|
||||
else if ((hsize = item.size/1024.0f) < 1024.0f) {
|
||||
printf("%.1fK\t", hsize);
|
||||
}
|
||||
else if ((hsize /= 1024.0f) < 1024.0f) {
|
||||
printf("%.1fM\t", hsize);
|
||||
}
|
||||
else {
|
||||
hsize /= 1024.0f;
|
||||
printf("%.1fG\t", hsize);
|
||||
}
|
||||
struct tm* tm = localtime(&item.mtime);
|
||||
printf("%04d-%02d-%02d %02d:%02d:%02d\t",
|
||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
printf("%s%s\n", item.name, item.type == 'd' ? "/" : "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "hexport.h"
|
||||
|
||||
typedef struct hdir_s {
|
||||
char name[256];
|
||||
char type; // f:file d:dir l:link b:block c:char s:socket p:pipe
|
||||
char reserverd;
|
||||
unsigned short mode;
|
||||
size_t size;
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
time_t ctime;
|
||||
} hdir_t;
|
||||
|
||||
// listdir: same as ls on unix, dir on win
|
||||
HV_EXPORT int listdir(const char* dir, std::list<hdir_t>& dirs);
|
||||
|
||||
#endif // HV_DIR_H_
|
||||
134
third_party/libhv/cpputil/hfile.h
vendored
Executable file
134
third_party/libhv/cpputil/hfile.h
vendored
Executable file
@@ -0,0 +1,134 @@
|
||||
#ifndef HV_FILE_H_
|
||||
#define HV_FILE_H_
|
||||
|
||||
#include <string> // for std::string
|
||||
|
||||
#include "hplatform.h" // for stat
|
||||
#include "hbuf.h" // for HBuf
|
||||
|
||||
class HFile {
|
||||
public:
|
||||
HFile() {
|
||||
filepath[0] = '\0';
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
~HFile() {
|
||||
close();
|
||||
}
|
||||
|
||||
int open(const char* filepath, const char* mode) {
|
||||
close();
|
||||
strncpy(this->filepath, filepath, MAX_PATH - 1);
|
||||
fp = fopen(filepath, mode);
|
||||
return fp ? 0 : errno;
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool isopen() {
|
||||
return fp != NULL;
|
||||
}
|
||||
|
||||
int remove() {
|
||||
close();
|
||||
return ::remove(filepath);
|
||||
}
|
||||
|
||||
int rename(const char* newpath) {
|
||||
close();
|
||||
return ::rename(filepath, newpath);
|
||||
}
|
||||
|
||||
size_t read(void* ptr, size_t len) {
|
||||
return fread(ptr, 1, len, fp);
|
||||
}
|
||||
|
||||
size_t write(const void* ptr, size_t len) {
|
||||
return fwrite(ptr, 1, len, fp);
|
||||
}
|
||||
|
||||
size_t write(const std::string& str) {
|
||||
return write(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
int seek(size_t offset, int whence = SEEK_SET) {
|
||||
return fseek(fp, offset, whence);
|
||||
}
|
||||
|
||||
int tell() {
|
||||
return ftell(fp);
|
||||
}
|
||||
|
||||
int flush() {
|
||||
return fflush(fp);
|
||||
}
|
||||
|
||||
static size_t size(const char* filepath) {
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
stat(filepath, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
return HFile::size(filepath);
|
||||
}
|
||||
|
||||
size_t readall(HBuf& buf) {
|
||||
size_t filesize = size();
|
||||
if (filesize == 0) return 0;
|
||||
buf.resize(filesize);
|
||||
return fread(buf.base, 1, filesize, fp);
|
||||
}
|
||||
|
||||
size_t readall(std::string& str) {
|
||||
size_t filesize = size();
|
||||
if (filesize == 0) return 0;
|
||||
str.resize(filesize);
|
||||
return fread((void*)str.data(), 1, filesize, fp);
|
||||
}
|
||||
|
||||
bool readline(std::string& str) {
|
||||
str.clear();
|
||||
char ch;
|
||||
while (fread(&ch, 1, 1, fp)) {
|
||||
if (ch == '\n') {
|
||||
// unix: LF
|
||||
return true;
|
||||
}
|
||||
if (ch == '\r') {
|
||||
// dos: CRLF
|
||||
// read LF
|
||||
if (fread(&ch, 1, 1, fp) && ch != '\n') {
|
||||
// mac: CR
|
||||
fseek(fp, -1, SEEK_CUR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
return str.length() != 0;
|
||||
}
|
||||
|
||||
int readrange(std::string& str, size_t from = 0, size_t to = 0) {
|
||||
size_t filesize = size();
|
||||
if (filesize == 0) return 0;
|
||||
if (to == 0 || to >= filesize) to = filesize - 1;
|
||||
size_t readbytes = to - from + 1;
|
||||
str.resize(readbytes);
|
||||
fseek(fp, from, SEEK_SET);
|
||||
return fread((void*)str.data(), 1, readbytes, fp);
|
||||
}
|
||||
|
||||
public:
|
||||
char filepath[MAX_PATH];
|
||||
FILE* fp;
|
||||
};
|
||||
|
||||
#endif // HV_FILE_H_
|
||||
55
third_party/libhv/cpputil/hmap.h
vendored
Executable file
55
third_party/libhv/cpputil/hmap.h
vendored
Executable file
@@ -0,0 +1,55 @@
|
||||
#ifndef HV_MAP_H_
|
||||
#define HV_MAP_H_
|
||||
|
||||
#include "hconfig.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
// MultiMap
|
||||
namespace std {
|
||||
/*
|
||||
int main() {
|
||||
std::MultiMap<std::string, std::string> kvs;
|
||||
kvs["name"] = "hw";
|
||||
kvs["filename"] = "1.jpg";
|
||||
kvs["filename"] = "2.jpg";
|
||||
//kvs.insert(std::pair<std::string,std::string>("name", "hw"));
|
||||
//kvs.insert(std::pair<std::string,std::string>("filename", "1.jpg"));
|
||||
//kvs.insert(std::pair<std::string,std::string>("filename", "2.jpg"));
|
||||
for (auto& pair : kvs) {
|
||||
printf("%s:%s\n", pair.first.c_str(), pair.second.c_str());
|
||||
}
|
||||
auto iter = kvs.find("filename");
|
||||
if (iter != kvs.end()) {
|
||||
for (int i = 0; i < kvs.count("filename"); ++i, ++iter) {
|
||||
printf("%s:%s\n", iter->first.c_str(), iter->second.c_str());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
template<typename Key,typename Value>
|
||||
class MultiMap : public multimap<Key, Value> {
|
||||
public:
|
||||
Value& operator[](Key key) {
|
||||
auto iter = this->insert(std::pair<Key,Value>(key,Value()));
|
||||
return (*iter).second;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef USE_MULTIMAP
|
||||
#define HV_MAP std::MultiMap
|
||||
#else
|
||||
#define HV_MAP std::map
|
||||
#endif
|
||||
|
||||
// KeyValue
|
||||
namespace hv {
|
||||
typedef std::map<std::string, std::string> keyval_t;
|
||||
typedef std::MultiMap<std::string, std::string> multi_keyval_t;
|
||||
typedef HV_MAP<std::string, std::string> KeyValue;
|
||||
}
|
||||
|
||||
#endif // HV_MAP_H_
|
||||
183
third_party/libhv/cpputil/hobjectpool.h
vendored
Executable file
183
third_party/libhv/cpputil/hobjectpool.h
vendored
Executable file
@@ -0,0 +1,183 @@
|
||||
#ifndef HV_OBJECT_POOL_H_
|
||||
#define HV_OBJECT_POOL_H_
|
||||
|
||||
/*
|
||||
* @usage unittest/objectpool_test.cpp
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#define DEFAULT_OBJECT_POOL_INIT_NUM 0
|
||||
#define DEFAULT_OBJECT_POOL_MAX_NUM 4
|
||||
#define DEFAULT_OBJECT_POOL_TIMEOUT 3000 // ms
|
||||
|
||||
template<class T>
|
||||
class HObjectFactory {
|
||||
public:
|
||||
static T* create() {
|
||||
return new T;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class TFactory = HObjectFactory<T>>
|
||||
class HObjectPool {
|
||||
public:
|
||||
HObjectPool(
|
||||
int init_num = DEFAULT_OBJECT_POOL_INIT_NUM,
|
||||
int max_num = DEFAULT_OBJECT_POOL_MAX_NUM,
|
||||
int timeout = DEFAULT_OBJECT_POOL_TIMEOUT)
|
||||
: _max_num(max_num)
|
||||
, _timeout(timeout)
|
||||
{
|
||||
for (int i = 0; i < init_num; ++i) {
|
||||
T* p = TFactory::create();
|
||||
if (p) {
|
||||
objects_.push_back(std::shared_ptr<T>(p));
|
||||
}
|
||||
}
|
||||
_object_num = objects_.size();
|
||||
}
|
||||
|
||||
~HObjectPool() {}
|
||||
|
||||
int ObjectNum() { return _object_num; }
|
||||
int IdleNum() { return objects_.size(); }
|
||||
int BorrowNum() { return ObjectNum() - IdleNum(); }
|
||||
|
||||
std::shared_ptr<T> TryBorrow() {
|
||||
std::shared_ptr<T> pObj = NULL;
|
||||
std::lock_guard<std::mutex> locker(mutex_);
|
||||
if (!objects_.empty()) {
|
||||
pObj = objects_.front();
|
||||
objects_.pop_front();
|
||||
}
|
||||
return pObj;
|
||||
}
|
||||
|
||||
std::shared_ptr<T> Borrow() {
|
||||
std::shared_ptr<T> pObj = TryBorrow();
|
||||
if (pObj) {
|
||||
return pObj;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> locker(mutex_);
|
||||
if (_object_num < _max_num) {
|
||||
++_object_num;
|
||||
// NOTE: unlock to avoid TFactory::create block
|
||||
mutex_.unlock();
|
||||
T* p = TFactory::create();
|
||||
mutex_.lock();
|
||||
if (!p) --_object_num;
|
||||
return std::shared_ptr<T>(p);
|
||||
}
|
||||
|
||||
if (_timeout > 0) {
|
||||
std::cv_status status = cond_.wait_for(locker, std::chrono::milliseconds(_timeout));
|
||||
if (status == std::cv_status::timeout) {
|
||||
return NULL;
|
||||
}
|
||||
if (!objects_.empty()) {
|
||||
pObj = objects_.front();
|
||||
objects_.pop_front();
|
||||
return pObj;
|
||||
}
|
||||
else {
|
||||
// WARN: No idle object
|
||||
}
|
||||
}
|
||||
return pObj;
|
||||
}
|
||||
|
||||
void Return(std::shared_ptr<T>& pObj) {
|
||||
if (!pObj) return;
|
||||
std::lock_guard<std::mutex> locker(mutex_);
|
||||
objects_.push_back(pObj);
|
||||
cond_.notify_one();
|
||||
}
|
||||
|
||||
bool Add(std::shared_ptr<T>& pObj) {
|
||||
std::lock_guard<std::mutex> locker(mutex_);
|
||||
if (_object_num >= _max_num) {
|
||||
return false;
|
||||
}
|
||||
objects_.push_back(pObj);
|
||||
++_object_num;
|
||||
cond_.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Remove(std::shared_ptr<T>& pObj) {
|
||||
std::lock_guard<std::mutex> locker(mutex_);
|
||||
auto iter = objects_.begin();
|
||||
while (iter != objects_.end()) {
|
||||
if (*iter == pObj) {
|
||||
iter = objects_.erase(iter);
|
||||
--_object_num;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
std::lock_guard<std::mutex> locker(mutex_);
|
||||
objects_.clear();
|
||||
_object_num = 0;
|
||||
}
|
||||
|
||||
int _object_num;
|
||||
int _max_num;
|
||||
int _timeout;
|
||||
private:
|
||||
std::list<std::shared_ptr<T>> objects_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
};
|
||||
|
||||
template<class T, class TFactory = HObjectFactory<T>>
|
||||
class HPoolObject {
|
||||
public:
|
||||
typedef HObjectPool<T, TFactory> PoolType;
|
||||
|
||||
HPoolObject(PoolType& pool) : pool_(pool)
|
||||
{
|
||||
sptr_ = pool_.Borrow();
|
||||
}
|
||||
|
||||
~HPoolObject() {
|
||||
if (sptr_) {
|
||||
pool_.Return(sptr_);
|
||||
}
|
||||
}
|
||||
|
||||
HPoolObject(const HPoolObject<T>&) = delete;
|
||||
HPoolObject<T>& operator=(const HPoolObject<T>&) = delete;
|
||||
|
||||
T* get() {
|
||||
return sptr_.get();
|
||||
}
|
||||
|
||||
operator bool() {
|
||||
return sptr_.get() != NULL;
|
||||
}
|
||||
|
||||
T* operator->() {
|
||||
return sptr_.get();
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *sptr_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
PoolType& pool_;
|
||||
std::shared_ptr<T> sptr_;
|
||||
};
|
||||
|
||||
#endif // HV_OBJECT_POOL_H_
|
||||
112
third_party/libhv/cpputil/hpath.cpp
vendored
Executable file
112
third_party/libhv/cpputil/hpath.cpp
vendored
Executable file
@@ -0,0 +1,112 @@
|
||||
#include "hpath.h"
|
||||
|
||||
#include "hplatform.h"
|
||||
|
||||
bool HPath::exists(const char* path) {
|
||||
return access(path, 0) == 0;
|
||||
}
|
||||
|
||||
bool HPath::isdir(const char* path) {
|
||||
if (access(path, 0) != 0) return false;
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
stat(path, &st);
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool HPath::isfile(const char* path) {
|
||||
if (access(path, 0) != 0) return false;
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
stat(path, &st);
|
||||
return S_ISREG(st.st_mode);
|
||||
}
|
||||
|
||||
bool HPath::islink(const char* path) {
|
||||
#ifdef OS_WIN
|
||||
return HPath::isdir(path) && (GetFileAttributesA(path) & FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
#else
|
||||
if (access(path, 0) != 0) return false;
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(st));
|
||||
lstat(path, &st);
|
||||
return S_ISLNK(st.st_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string HPath::basename(const std::string& filepath) {
|
||||
std::string::size_type pos1 = filepath.find_last_not_of("/\\");
|
||||
if (pos1 == std::string::npos) {
|
||||
return "/";
|
||||
}
|
||||
std::string::size_type pos2 = filepath.find_last_of("/\\", pos1);
|
||||
if (pos2 == std::string::npos) {
|
||||
pos2 = 0;
|
||||
} else {
|
||||
pos2++;
|
||||
}
|
||||
|
||||
return filepath.substr(pos2, pos1-pos2+1);
|
||||
}
|
||||
|
||||
std::string HPath::dirname(const std::string& filepath) {
|
||||
std::string::size_type pos1 = filepath.find_last_not_of("/\\");
|
||||
if (pos1 == std::string::npos) {
|
||||
return "/";
|
||||
}
|
||||
std::string::size_type pos2 = filepath.find_last_of("/\\", pos1);
|
||||
if (pos2 == std::string::npos) {
|
||||
return ".";
|
||||
} else if (pos2 == 0) {
|
||||
pos2 = 1;
|
||||
}
|
||||
|
||||
return filepath.substr(0, pos2);
|
||||
}
|
||||
|
||||
std::string HPath::filename(const std::string& filepath) {
|
||||
std::string::size_type pos1 = filepath.find_last_of("/\\");
|
||||
if (pos1 == std::string::npos) {
|
||||
pos1 = 0;
|
||||
} else {
|
||||
pos1++;
|
||||
}
|
||||
std::string file = filepath.substr(pos1);
|
||||
|
||||
std::string::size_type pos2 = file.find_last_of(".");
|
||||
if (pos2 == std::string::npos) {
|
||||
return file;
|
||||
}
|
||||
return file.substr(0, pos2);
|
||||
}
|
||||
|
||||
std::string HPath::suffixname(const std::string& filepath) {
|
||||
std::string::size_type pos1 = filepath.find_last_of("/\\");
|
||||
if (pos1 == std::string::npos) {
|
||||
pos1 = 0;
|
||||
} else {
|
||||
pos1++;
|
||||
}
|
||||
std::string file = filepath.substr(pos1);
|
||||
|
||||
std::string::size_type pos2 = file.find_last_of(".");
|
||||
if (pos2 == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
return file.substr(pos2+1);
|
||||
}
|
||||
|
||||
std::string HPath::join(const std::string& dir, const std::string& filename) {
|
||||
char separator = '/';
|
||||
#ifdef OS_WIN
|
||||
if (dir.find_first_of("\\") != std::string::npos) {
|
||||
separator = '\\';
|
||||
}
|
||||
#endif
|
||||
std::string filepath(dir);
|
||||
if (dir[dir.length()-1] != separator) {
|
||||
filepath += separator;
|
||||
}
|
||||
filepath += filename;
|
||||
return filepath;
|
||||
}
|
||||
28
third_party/libhv/cpputil/hpath.h
vendored
Executable file
28
third_party/libhv/cpputil/hpath.h
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
#ifndef HV_PATH_H_
|
||||
#define HV_PATH_H_
|
||||
|
||||
#include <string> // for std::string
|
||||
|
||||
#include "hexport.h"
|
||||
|
||||
class HV_EXPORT HPath {
|
||||
public:
|
||||
static bool exists(const char* path);
|
||||
static bool isdir(const char* path);
|
||||
static bool isfile(const char* path);
|
||||
static bool islink(const char* path);
|
||||
|
||||
// filepath = /mnt/share/image/test.jpg
|
||||
// basename = test.jpg
|
||||
// dirname = /mnt/share/image
|
||||
// filename = test
|
||||
// suffixname = jpg
|
||||
static std::string basename(const std::string& filepath);
|
||||
static std::string dirname(const std::string& filepath);
|
||||
static std::string filename(const std::string& filepath);
|
||||
static std::string suffixname(const std::string& filepath);
|
||||
|
||||
static std::string join(const std::string& dir, const std::string& filename);
|
||||
};
|
||||
|
||||
#endif // HV_PATH_H_
|
||||
79
third_party/libhv/cpputil/hscope.h
vendored
Executable file
79
third_party/libhv/cpputil/hscope.h
vendored
Executable file
@@ -0,0 +1,79 @@
|
||||
#ifndef HV_SCOPE_H_
|
||||
#define HV_SCOPE_H_
|
||||
|
||||
#include <functional>
|
||||
typedef std::function<void()> Function;
|
||||
|
||||
#include "hdef.h"
|
||||
|
||||
// same as golang defer
|
||||
class Defer {
|
||||
public:
|
||||
Defer(Function&& fn) : _fn(std::move(fn)) {}
|
||||
~Defer() { if(_fn) _fn();}
|
||||
private:
|
||||
Function _fn;
|
||||
};
|
||||
#define defer(code) Defer STRINGCAT(_defer_, __LINE__)([&](){code});
|
||||
|
||||
class ScopeCleanup {
|
||||
public:
|
||||
template<typename Fn, typename... Args>
|
||||
ScopeCleanup(Fn&& fn, Args&&... args) {
|
||||
_cleanup = std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
~ScopeCleanup() {
|
||||
_cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
Function _cleanup;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ScopeFree {
|
||||
public:
|
||||
ScopeFree(T* p) : _p(p) {}
|
||||
~ScopeFree() {SAFE_FREE(_p);}
|
||||
private:
|
||||
T* _p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ScopeDelete {
|
||||
public:
|
||||
ScopeDelete(T* p) : _p(p) {}
|
||||
~ScopeDelete() {SAFE_DELETE(_p);}
|
||||
private:
|
||||
T* _p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ScopeDeleteArray {
|
||||
public:
|
||||
ScopeDeleteArray(T* p) : _p(p) {}
|
||||
~ScopeDeleteArray() {SAFE_DELETE_ARRAY(_p);}
|
||||
private:
|
||||
T* _p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ScopeRelease {
|
||||
public:
|
||||
ScopeRelease(T* p) : _p(p) {}
|
||||
~ScopeRelease() {SAFE_RELEASE(_p);}
|
||||
private:
|
||||
T* _p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ScopeLock {
|
||||
public:
|
||||
ScopeLock(T& mutex) : _mutex(mutex) {_mutex.lock();}
|
||||
~ScopeLock() {_mutex.unlock();}
|
||||
private:
|
||||
T& _mutex;
|
||||
};
|
||||
|
||||
#endif // HV_SCOPE_H_
|
||||
227
third_party/libhv/cpputil/hstring.cpp
vendored
Executable file
227
third_party/libhv/cpputil/hstring.cpp
vendored
Executable file
@@ -0,0 +1,227 @@
|
||||
#include "hstring.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace hv {
|
||||
|
||||
std::string empty_string;
|
||||
std::map<std::string, std::string> empty_map;
|
||||
|
||||
std::string& toupper(std::string& str) {
|
||||
// std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
||||
char* p = (char*)str.c_str();
|
||||
while (*p != '\0') {
|
||||
if (*p >= 'a' && *p <= 'z') {
|
||||
*p &= ~0x20;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string& tolower(std::string& str) {
|
||||
// std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
char* p = (char*)str.c_str();
|
||||
while (*p != '\0') {
|
||||
if (*p >= 'A' && *p <= 'Z') {
|
||||
*p |= 0x20;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string& reverse(std::string& str) {
|
||||
// std::reverse(str.begin(), str.end());
|
||||
char* b = (char*)str.c_str();
|
||||
char* e = b + str.length() - 1;
|
||||
char tmp;
|
||||
while (e > b) {
|
||||
tmp = *e;
|
||||
*e = *b;
|
||||
*b = tmp;
|
||||
--e;
|
||||
++b;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
bool startswith(const std::string& str, const std::string& start) {
|
||||
if (str.length() < start.length()) return false;
|
||||
return str.compare(0, start.length(), start) == 0;
|
||||
}
|
||||
|
||||
bool endswith(const std::string& str, const std::string& end) {
|
||||
if (str.length() < end.length()) return false;
|
||||
return str.compare(str.length() - end.length(), end.length(), end) == 0;
|
||||
}
|
||||
|
||||
bool contains(const std::string& str, const std::string& sub) {
|
||||
if (str.length() < sub.length()) return false;
|
||||
return str.find(sub) != std::string::npos;
|
||||
}
|
||||
|
||||
static inline int vscprintf(const char* fmt, va_list ap) {
|
||||
return vsnprintf(NULL, 0, fmt, ap);
|
||||
}
|
||||
|
||||
std::string asprintf(const char* fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int len = vscprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
std::string str;
|
||||
str.reserve(len+1);
|
||||
// must resize to set str.size
|
||||
str.resize(len);
|
||||
// must recall va_start on unix
|
||||
va_start(ap, fmt);
|
||||
vsnprintf((char*)str.data(), len+1, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
StringList split(const std::string& str, char delim) {
|
||||
/*
|
||||
std::stringstream ss;
|
||||
ss << str;
|
||||
string item;
|
||||
StringList res;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
res.push_back(item);
|
||||
}
|
||||
return res;
|
||||
*/
|
||||
const char* p = str.c_str();
|
||||
const char* value = p;
|
||||
StringList res;
|
||||
while (*p != '\0') {
|
||||
if (*p == delim) {
|
||||
res.push_back(std::string(value, p-value));
|
||||
value = p+1;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
res.push_back(value);
|
||||
return res;
|
||||
}
|
||||
|
||||
hv::KeyValue splitKV(const std::string& str, char kv_kv, char k_v) {
|
||||
enum {
|
||||
s_key,
|
||||
s_value,
|
||||
} state = s_key;
|
||||
const char* p = str.c_str();
|
||||
const char* key = p;
|
||||
const char* value = NULL;
|
||||
int key_len = 0;
|
||||
int value_len = 0;
|
||||
hv::KeyValue kvs;
|
||||
while (*p != '\0') {
|
||||
if (*p == kv_kv) {
|
||||
if (key_len && value_len) {
|
||||
kvs[std::string(key, key_len)] = std::string(value, value_len);
|
||||
key_len = value_len = 0;
|
||||
}
|
||||
state = s_key;
|
||||
key = p+1;
|
||||
}
|
||||
else if (*p == k_v && state != s_value) {
|
||||
state = s_value;
|
||||
value = p+1;
|
||||
}
|
||||
else {
|
||||
state == s_key ? ++key_len : ++value_len;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
if (key_len && value_len) {
|
||||
kvs[std::string(key, key_len)] = std::string(value, value_len);
|
||||
}
|
||||
return kvs;
|
||||
}
|
||||
|
||||
std::string trim(const std::string& str, const char* chars) {
|
||||
std::string::size_type pos1 = str.find_first_not_of(chars);
|
||||
if (pos1 == std::string::npos) return "";
|
||||
|
||||
std::string::size_type pos2 = str.find_last_not_of(chars);
|
||||
return str.substr(pos1, pos2-pos1+1);
|
||||
}
|
||||
|
||||
std::string ltrim(const std::string& str, const char* chars) {
|
||||
std::string::size_type pos = str.find_first_not_of(chars);
|
||||
if (pos == std::string::npos) return "";
|
||||
return str.substr(pos);
|
||||
}
|
||||
|
||||
std::string rtrim(const std::string& str, const char* chars) {
|
||||
std::string::size_type pos = str.find_last_not_of(chars);
|
||||
return str.substr(0, pos+1);
|
||||
}
|
||||
|
||||
std::string trim_pairs(const std::string& str, const char* pairs) {
|
||||
const char* s = str.c_str();
|
||||
const char* e = str.c_str() + str.size() - 1;
|
||||
const char* p = pairs;
|
||||
bool is_pair = false;
|
||||
while (*p != '\0' && *(p+1) != '\0') {
|
||||
if (*s == *p && *e == *(p+1)) {
|
||||
is_pair = true;
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
return is_pair ? str.substr(1, str.size()-2) : str;
|
||||
}
|
||||
|
||||
std::string replace(const std::string& str, const std::string& find, const std::string& rep) {
|
||||
std::string res(str);
|
||||
std::string::size_type pos = res.find(find);
|
||||
if (pos != std::string::npos) {
|
||||
res.replace(pos, find.size(), rep);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string replaceAll(const std::string& str, const std::string& find, const std::string& rep) {
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type a = find.size();
|
||||
std::string::size_type b = rep.size();
|
||||
|
||||
std::string res(str);
|
||||
while ((pos = res.find(find, pos)) != std::string::npos) {
|
||||
res.replace(pos, a, rep);
|
||||
pos += b;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void NetAddr::from_string(const std::string& ipport) {
|
||||
auto pos = ipport.find_last_of(':');
|
||||
if (pos != std::string::npos) {
|
||||
ip = trim_pairs(ipport.substr(0, pos), "[]");
|
||||
std::string strPort = ipport.substr(pos + 1);
|
||||
port = atoi(strPort.c_str());
|
||||
} else if (ipport.find('.') != std::string::npos) {
|
||||
ip = ipport;
|
||||
port = 0;
|
||||
} else {
|
||||
port = atoi(ipport.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string NetAddr::to_string() {
|
||||
const char* fmt = "%s:%d";
|
||||
if (ip.find(':') != std::string::npos) {
|
||||
fmt = "[%s]:%d";
|
||||
}
|
||||
return hv::asprintf(fmt, ip.c_str(), port);
|
||||
}
|
||||
|
||||
} // end namespace hv
|
||||
92
third_party/libhv/cpputil/hstring.h
vendored
Executable file
92
third_party/libhv/cpputil/hstring.h
vendored
Executable file
@@ -0,0 +1,92 @@
|
||||
#ifndef HV_STRING_H_
|
||||
#define HV_STRING_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "hexport.h"
|
||||
#include "hplatform.h"
|
||||
#include "hmap.h"
|
||||
|
||||
#define SPACE_CHARS " \t\r\n"
|
||||
#define PAIR_CHARS "{}[]()<>\"\"\'\'``"
|
||||
|
||||
namespace hv {
|
||||
|
||||
HV_EXPORT extern std::string empty_string;
|
||||
HV_EXPORT extern std::map<std::string, std::string> empty_map;
|
||||
|
||||
typedef std::vector<std::string> StringList;
|
||||
|
||||
// std::map<std::string, std::string, StringCaseLess>
|
||||
class StringCaseLess : public std::less<std::string> {
|
||||
public:
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const {
|
||||
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: low-version NDK not provide std::to_string
|
||||
template<typename T>
|
||||
HV_INLINE std::string to_string(const T& t) {
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HV_INLINE T from_string(const std::string& str) {
|
||||
T t;
|
||||
std::istringstream iss(str);
|
||||
iss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HV_INLINE void print(const T& t) {
|
||||
std::cout << t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HV_INLINE void println(const T& t) {
|
||||
std::cout << t << std::endl;
|
||||
}
|
||||
|
||||
HV_EXPORT std::string& toupper(std::string& str);
|
||||
HV_EXPORT std::string& tolower(std::string& str);
|
||||
HV_EXPORT std::string& reverse(std::string& str);
|
||||
|
||||
HV_EXPORT bool startswith(const std::string& str, const std::string& start);
|
||||
HV_EXPORT bool endswith(const std::string& str, const std::string& end);
|
||||
HV_EXPORT bool contains(const std::string& str, const std::string& sub);
|
||||
|
||||
HV_EXPORT std::string asprintf(const char* fmt, ...);
|
||||
// x,y,z
|
||||
HV_EXPORT StringList split(const std::string& str, char delim = ',');
|
||||
// k1=v1&k2=v2
|
||||
HV_EXPORT hv::KeyValue splitKV(const std::string& str, char kv_kv = '&', char k_v = '=');
|
||||
HV_EXPORT std::string trim(const std::string& str, const char* chars = SPACE_CHARS);
|
||||
HV_EXPORT std::string ltrim(const std::string& str, const char* chars = SPACE_CHARS);
|
||||
HV_EXPORT std::string rtrim(const std::string& str, const char* chars = SPACE_CHARS);
|
||||
HV_EXPORT std::string trim_pairs(const std::string& str, const char* pairs = PAIR_CHARS);
|
||||
HV_EXPORT std::string replace(const std::string& str, const std::string& find, const std::string& rep);
|
||||
HV_EXPORT std::string replaceAll(const std::string& str, const std::string& find, const std::string& rep);
|
||||
|
||||
struct HV_EXPORT NetAddr {
|
||||
std::string ip;
|
||||
int port;
|
||||
|
||||
NetAddr() : port(0) {}
|
||||
NetAddr(const std::string& _ip, int _port) : ip(_ip), port(_port) {}
|
||||
NetAddr(const std::string& ipport) { from_string(ipport); }
|
||||
|
||||
void from_string(const std::string& ipport);
|
||||
std::string to_string();
|
||||
};
|
||||
|
||||
} // end namespace hv
|
||||
|
||||
#endif // HV_STRING_H_
|
||||
249
third_party/libhv/cpputil/hthreadpool.h
vendored
Executable file
249
third_party/libhv/cpputil/hthreadpool.h
vendored
Executable file
@@ -0,0 +1,249 @@
|
||||
#ifndef HV_THREAD_POOL_H_
|
||||
#define HV_THREAD_POOL_H_
|
||||
|
||||
/*
|
||||
* @usage unittest/threadpool_test.cpp
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <thread>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
|
||||
#define DEFAULT_THREAD_POOL_MIN_THREAD_NUM 1
|
||||
#define DEFAULT_THREAD_POOL_MAX_THREAD_NUM std::thread::hardware_concurrency()
|
||||
#define DEFAULT_THREAD_POOL_MAX_IDLE_TIME 60000 // ms
|
||||
|
||||
class HThreadPool {
|
||||
public:
|
||||
using Task = std::function<void()>;
|
||||
|
||||
HThreadPool(int min_threads = DEFAULT_THREAD_POOL_MIN_THREAD_NUM,
|
||||
int max_threads = DEFAULT_THREAD_POOL_MAX_THREAD_NUM,
|
||||
int max_idle_ms = DEFAULT_THREAD_POOL_MAX_IDLE_TIME)
|
||||
: min_thread_num(min_threads)
|
||||
, max_thread_num(max_threads)
|
||||
, max_idle_time(max_idle_ms)
|
||||
, status(STOP)
|
||||
, cur_thread_num(0)
|
||||
, idle_thread_num(0)
|
||||
{}
|
||||
|
||||
virtual ~HThreadPool() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void setMinThreadNum(int min_threads) {
|
||||
min_thread_num = min_threads;
|
||||
}
|
||||
void setMaxThreadNum(int max_threads) {
|
||||
max_thread_num = max_threads;
|
||||
}
|
||||
void setMaxIdleTime(int ms) {
|
||||
max_idle_time = ms;
|
||||
}
|
||||
int currentThreadNum() {
|
||||
return cur_thread_num;
|
||||
}
|
||||
int idleThreadNum() {
|
||||
return idle_thread_num;
|
||||
}
|
||||
size_t taskNum() {
|
||||
std::lock_guard<std::mutex> locker(task_mutex);
|
||||
return tasks.size();
|
||||
}
|
||||
bool isStarted() {
|
||||
return status != STOP;
|
||||
}
|
||||
bool isStopped() {
|
||||
return status == STOP;
|
||||
}
|
||||
|
||||
int start(int start_threads = 0) {
|
||||
if (status != STOP) return -1;
|
||||
status = RUNNING;
|
||||
if (start_threads < min_thread_num) start_threads = min_thread_num;
|
||||
if (start_threads > max_thread_num) start_threads = max_thread_num;
|
||||
for (int i = 0; i < start_threads; ++i) {
|
||||
createThread();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stop() {
|
||||
if (status == STOP) return -1;
|
||||
status = STOP;
|
||||
task_cond.notify_all();
|
||||
for (auto& i : threads) {
|
||||
if (i.thread->joinable()) {
|
||||
i.thread->join();
|
||||
}
|
||||
}
|
||||
threads.clear();
|
||||
cur_thread_num = 0;
|
||||
idle_thread_num = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pause() {
|
||||
if (status == RUNNING) {
|
||||
status = PAUSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resume() {
|
||||
if (status == PAUSE) {
|
||||
status = RUNNING;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wait() {
|
||||
while (status != STOP) {
|
||||
if (tasks.empty() && idle_thread_num == cur_thread_num) {
|
||||
break;
|
||||
}
|
||||
std::this_thread::yield();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a future, calling future.get() will wait task done and return RetType.
|
||||
* commit(fn, args...)
|
||||
* commit(std::bind(&Class::mem_fn, &obj))
|
||||
* commit(std::mem_fn(&Class::mem_fn, &obj))
|
||||
*
|
||||
*/
|
||||
template<class Fn, class... Args>
|
||||
auto commit(Fn&& fn, Args&&... args) -> std::future<decltype(fn(args...))> {
|
||||
if (status == STOP) start();
|
||||
if (idle_thread_num <= tasks.size() && cur_thread_num < max_thread_num) {
|
||||
createThread();
|
||||
}
|
||||
using RetType = decltype(fn(args...));
|
||||
auto task = std::make_shared<std::packaged_task<RetType()> >(
|
||||
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...));
|
||||
std::future<RetType> future = task->get_future();
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(task_mutex);
|
||||
tasks.emplace([task]{
|
||||
(*task)();
|
||||
});
|
||||
}
|
||||
|
||||
task_cond.notify_one();
|
||||
return future;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool createThread() {
|
||||
if (cur_thread_num >= max_thread_num) return false;
|
||||
std::thread* thread = new std::thread([this] {
|
||||
while (status != STOP) {
|
||||
while (status == PAUSE) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
Task task;
|
||||
{
|
||||
std::unique_lock<std::mutex> locker(task_mutex);
|
||||
task_cond.wait_for(locker, std::chrono::milliseconds(max_idle_time), [this]() {
|
||||
return status == STOP || !tasks.empty();
|
||||
});
|
||||
if (status == STOP) return;
|
||||
if (tasks.empty()) {
|
||||
if (cur_thread_num > min_thread_num) {
|
||||
delThread(std::this_thread::get_id());
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
--idle_thread_num;
|
||||
task = std::move(tasks.front());
|
||||
tasks.pop();
|
||||
}
|
||||
if (task) {
|
||||
task();
|
||||
++idle_thread_num;
|
||||
}
|
||||
}
|
||||
});
|
||||
addThread(thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
void addThread(std::thread* thread) {
|
||||
thread_mutex.lock();
|
||||
++cur_thread_num;
|
||||
++idle_thread_num;
|
||||
ThreadData data;
|
||||
data.thread = std::shared_ptr<std::thread>(thread);
|
||||
data.id = thread->get_id();
|
||||
data.status = RUNNING;
|
||||
data.start_time = time(NULL);
|
||||
data.stop_time = 0;
|
||||
threads.emplace_back(data);
|
||||
thread_mutex.unlock();
|
||||
}
|
||||
|
||||
void delThread(std::thread::id id) {
|
||||
time_t now = time(NULL);
|
||||
thread_mutex.lock();
|
||||
--cur_thread_num;
|
||||
--idle_thread_num;
|
||||
auto iter = threads.begin();
|
||||
while (iter != threads.end()) {
|
||||
if (iter->status == STOP && now > iter->stop_time) {
|
||||
if (iter->thread->joinable()) {
|
||||
iter->thread->join();
|
||||
iter = threads.erase(iter);
|
||||
continue;
|
||||
}
|
||||
} else if (iter->id == id) {
|
||||
iter->status = STOP;
|
||||
iter->stop_time = time(NULL);
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
thread_mutex.unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
int min_thread_num;
|
||||
int max_thread_num;
|
||||
int max_idle_time;
|
||||
|
||||
protected:
|
||||
enum Status {
|
||||
STOP,
|
||||
RUNNING,
|
||||
PAUSE,
|
||||
};
|
||||
struct ThreadData {
|
||||
std::shared_ptr<std::thread> thread;
|
||||
std::thread::id id;
|
||||
Status status;
|
||||
time_t start_time;
|
||||
time_t stop_time;
|
||||
};
|
||||
std::atomic<Status> status;
|
||||
std::atomic<int> cur_thread_num;
|
||||
std::atomic<int> idle_thread_num;
|
||||
std::list<ThreadData> threads;
|
||||
std::mutex thread_mutex;
|
||||
std::queue<Task> tasks;
|
||||
std::mutex task_mutex;
|
||||
std::condition_variable task_cond;
|
||||
};
|
||||
|
||||
#endif // HV_THREAD_POOL_H_
|
||||
206
third_party/libhv/cpputil/hurl.cpp
vendored
Executable file
206
third_party/libhv/cpputil/hurl.cpp
vendored
Executable file
@@ -0,0 +1,206 @@
|
||||
#include "hurl.h"
|
||||
|
||||
#include "hdef.h"
|
||||
#include "hbase.h"
|
||||
|
||||
/*
|
||||
static bool Curl_isunreserved(unsigned char in)
|
||||
{
|
||||
switch(in) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
case '-': case '.': case '_': case '~':
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FLASE;
|
||||
}
|
||||
*/
|
||||
|
||||
static inline bool is_unambiguous(char c) {
|
||||
return IS_ALPHANUM(c) ||
|
||||
c == '-' ||
|
||||
c == '_' ||
|
||||
c == '.' ||
|
||||
c == '~';
|
||||
}
|
||||
|
||||
static inline bool char_in_str(char c, const char* str) {
|
||||
const char* p = str;
|
||||
while (*p && *p != c) ++p;
|
||||
return *p != '\0';
|
||||
}
|
||||
|
||||
static inline unsigned char hex2i(char hex) {
|
||||
return hex <= '9' ? hex - '0' :
|
||||
hex <= 'F' ? hex - 'A' + 10 : hex - 'a' + 10;
|
||||
}
|
||||
|
||||
std::string HUrl::escape(const std::string& str, const char* unescaped_chars) {
|
||||
std::string ostr;
|
||||
static char tab[] = "0123456789ABCDEF";
|
||||
const unsigned char* p = reinterpret_cast<const unsigned char*>(str.c_str());
|
||||
char szHex[4] = "%00";
|
||||
while (*p != '\0') {
|
||||
if (is_unambiguous(*p) || char_in_str(*p, unescaped_chars)) {
|
||||
ostr += *p;
|
||||
}
|
||||
else {
|
||||
szHex[1] = tab[*p >> 4];
|
||||
szHex[2] = tab[*p & 0xF];
|
||||
ostr += szHex;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return ostr;
|
||||
}
|
||||
|
||||
std::string HUrl::unescape(const std::string& str) {
|
||||
std::string ostr;
|
||||
const char* p = str.c_str();
|
||||
while (*p != '\0') {
|
||||
if (*p == '%' &&
|
||||
IS_HEX(p[1]) &&
|
||||
IS_HEX(p[2])) {
|
||||
ostr += ((hex2i(p[1]) << 4) | hex2i(p[2]));
|
||||
p += 3;
|
||||
}
|
||||
else {
|
||||
if (*p == '+') {
|
||||
ostr += ' ';
|
||||
} else {
|
||||
ostr += *p;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
return ostr;
|
||||
}
|
||||
|
||||
void HUrl::reset() {
|
||||
url.clear();
|
||||
scheme.clear();
|
||||
username.clear();
|
||||
password.clear();
|
||||
host.clear();
|
||||
port = 0;
|
||||
path.clear();
|
||||
query.clear();
|
||||
fragment.clear();
|
||||
}
|
||||
|
||||
bool HUrl::parse(const std::string& url) {
|
||||
reset();
|
||||
this->url = url;
|
||||
hurl_t stURL;
|
||||
if (hv_parse_url(&stURL, url.c_str()) != 0) {
|
||||
return false;
|
||||
}
|
||||
int len = stURL.fields[HV_URL_SCHEME].len;
|
||||
if (len > 0) {
|
||||
scheme = url.substr(stURL.fields[HV_URL_SCHEME].off, len);
|
||||
}
|
||||
len = stURL.fields[HV_URL_USERNAME].len;
|
||||
if (len > 0) {
|
||||
username = url.substr(stURL.fields[HV_URL_USERNAME].off, len);
|
||||
len = stURL.fields[HV_URL_PASSWORD].len;
|
||||
if (len > 0) {
|
||||
password = url.substr(stURL.fields[HV_URL_PASSWORD].off, len);
|
||||
}
|
||||
}
|
||||
len = stURL.fields[HV_URL_HOST].len;
|
||||
if (len > 0) {
|
||||
host = url.substr(stURL.fields[HV_URL_HOST].off, len);
|
||||
}
|
||||
port = stURL.port;
|
||||
len = stURL.fields[HV_URL_PATH].len;
|
||||
if (len > 0) {
|
||||
path = url.substr(stURL.fields[HV_URL_PATH].off, len);
|
||||
} else {
|
||||
path = "/";
|
||||
}
|
||||
len = stURL.fields[HV_URL_QUERY].len;
|
||||
if (len > 0) {
|
||||
query = url.substr(stURL.fields[HV_URL_QUERY].off, len);
|
||||
}
|
||||
len = stURL.fields[HV_URL_FRAGMENT].len;
|
||||
if (len > 0) {
|
||||
fragment = url.substr(stURL.fields[HV_URL_FRAGMENT].off, len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& HUrl::dump() {
|
||||
url.clear();
|
||||
// scheme://
|
||||
if (!scheme.empty()) {
|
||||
url += scheme;
|
||||
url += "://";
|
||||
}
|
||||
// user:pswd@
|
||||
if (!username.empty()) {
|
||||
url += username;
|
||||
if (!password.empty()) {
|
||||
url += ":";
|
||||
url += password;
|
||||
}
|
||||
url += "@";
|
||||
}
|
||||
// host:port
|
||||
if (!host.empty()) {
|
||||
url += host;
|
||||
if (port != 80 && port != 443) {
|
||||
char buf[16] = {0};
|
||||
snprintf(buf, sizeof(buf), ":%d", port);
|
||||
url += port;
|
||||
}
|
||||
}
|
||||
// /path
|
||||
if (!path.empty()) {
|
||||
url += path;
|
||||
}
|
||||
// ?query
|
||||
if (!query.empty()) {
|
||||
url += '?';
|
||||
url += query;
|
||||
}
|
||||
// #fragment
|
||||
if (!fragment.empty()) {
|
||||
url += '#';
|
||||
url += fragment;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
namespace hv {
|
||||
|
||||
std::string escapeHTML(const std::string& str) {
|
||||
std::string ostr;
|
||||
const char* p = str.c_str();
|
||||
while (*p != '\0') {
|
||||
switch (*p) {
|
||||
case '<': ostr += "<"; break;
|
||||
case '>': ostr += ">"; break;
|
||||
case '&': ostr += "&"; break;
|
||||
case '\"': ostr += """; break;
|
||||
case '\'': ostr += "'"; break;
|
||||
// case ' ': ostr += " "; break;
|
||||
default: ostr += *p; break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return ostr;
|
||||
}
|
||||
|
||||
}
|
||||
41
third_party/libhv/cpputil/hurl.h
vendored
Executable file
41
third_party/libhv/cpputil/hurl.h
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
#ifndef HV_URL_H_
|
||||
#define HV_URL_H_
|
||||
|
||||
#include <string> // import std::string
|
||||
|
||||
#include "hexport.h"
|
||||
|
||||
class HV_EXPORT HUrl {
|
||||
public:
|
||||
static std::string escape(const std::string& str, const char* unescaped_chars = "");
|
||||
static std::string unescape(const std::string& str);
|
||||
|
||||
HUrl() : port(0) {}
|
||||
~HUrl() {}
|
||||
|
||||
void reset();
|
||||
bool parse(const std::string& url);
|
||||
const std::string& dump();
|
||||
|
||||
std::string url;
|
||||
std::string scheme;
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string host;
|
||||
int port;
|
||||
std::string path;
|
||||
std::string query;
|
||||
std::string fragment;
|
||||
};
|
||||
|
||||
namespace hv {
|
||||
|
||||
HV_INLINE std::string escapeURL(const std::string& url) {
|
||||
return HUrl::escape(url, ":/@?=&#+");
|
||||
}
|
||||
|
||||
HV_EXPORT std::string escapeHTML(const std::string& str);
|
||||
|
||||
} // end namespace hv
|
||||
|
||||
#endif // HV_URL_H_
|
||||
223
third_party/libhv/cpputil/ifconfig.cpp
vendored
Executable file
223
third_party/libhv/cpputil/ifconfig.cpp
vendored
Executable file
@@ -0,0 +1,223 @@
|
||||
#include "ifconfig.h"
|
||||
|
||||
#include "hplatform.h"
|
||||
|
||||
#ifdef OS_LINUX
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int ifconfig(std::vector<ifconfig_t>& ifcs) {
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
return -10;
|
||||
}
|
||||
|
||||
struct ifconf ifc;
|
||||
char buf[1024];
|
||||
ifc.ifc_len = sizeof(buf);
|
||||
ifc.ifc_buf = buf;
|
||||
|
||||
int iRet = ioctl(sock, SIOCGIFCONF, &ifc);
|
||||
if (iRet != 0) {
|
||||
close(sock);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int cnt = ifc.ifc_len / sizeof(struct ifreq);
|
||||
//printf("ifc.size=%d\n", cnt);
|
||||
if (cnt == 0) {
|
||||
close(sock);
|
||||
return -20;
|
||||
}
|
||||
|
||||
struct ifreq ifr;
|
||||
ifcs.clear();
|
||||
ifconfig_t tmp;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
// name
|
||||
strcpy(ifr.ifr_name, ifc.ifc_req[i].ifr_name);
|
||||
//printf("name: %s\n", ifr.ifr_name);
|
||||
strncpy(tmp.name, ifr.ifr_name, sizeof(tmp.name));
|
||||
// flags
|
||||
//iRet = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||
//short flags = ifr.ifr_flags;
|
||||
// addr
|
||||
iRet = ioctl(sock, SIOCGIFADDR, &ifr);
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
|
||||
char* ip = inet_ntoa(addr->sin_addr);
|
||||
//printf("ip: %s\n", ip);
|
||||
strncpy(tmp.ip, ip, sizeof(tmp.ip));
|
||||
// netmask
|
||||
iRet = ioctl(sock, SIOCGIFNETMASK, &ifr);
|
||||
addr = (struct sockaddr_in*)&ifr.ifr_netmask;
|
||||
char* netmask = inet_ntoa(addr->sin_addr);
|
||||
//printf("netmask: %s\n", netmask);
|
||||
strncpy(tmp.mask, netmask, sizeof(tmp.mask));
|
||||
// broadaddr
|
||||
iRet = ioctl(sock, SIOCGIFBRDADDR, &ifr);
|
||||
addr = (struct sockaddr_in*)&ifr.ifr_broadaddr;
|
||||
char* broadaddr = inet_ntoa(addr->sin_addr);
|
||||
//printf("broadaddr: %s\n", broadaddr);
|
||||
strncpy(tmp.broadcast, broadaddr, sizeof(tmp.broadcast));
|
||||
// hwaddr
|
||||
iRet = ioctl(sock, SIOCGIFHWADDR, &ifr);
|
||||
snprintf(tmp.mac, sizeof(tmp.mac), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
|
||||
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
|
||||
//printf("mac: %s\n", tmp.mac);
|
||||
//printf("\n");
|
||||
|
||||
if (strcmp(tmp.ip, "0.0.0.0") == 0 ||
|
||||
strcmp(tmp.ip, "127.0.0.1") == 0 ||
|
||||
strcmp(tmp.mac, "00:00:00:00:00:00") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ifcs.push_back(tmp);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return 0;
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <iphlpapi.h>
|
||||
int ifconfig(std::vector<ifconfig_t>& ifcs) {
|
||||
PIP_ADAPTER_ADDRESSES pAddrs = NULL;
|
||||
ULONG buflen = 0;
|
||||
GetAdaptersAddresses(AF_INET, 0, NULL, pAddrs, &buflen);
|
||||
pAddrs = (PIP_ADAPTER_ADDRESSES)malloc(buflen);
|
||||
GetAdaptersAddresses(AF_INET, 0, NULL, pAddrs, &buflen);
|
||||
|
||||
PIP_ADAPTER_INFO pInfos = NULL;
|
||||
buflen = 0;
|
||||
GetAdaptersInfo(pInfos, &buflen);
|
||||
pInfos = (PIP_ADAPTER_INFO)malloc(buflen);
|
||||
GetAdaptersInfo(pInfos, &buflen);
|
||||
|
||||
ifconfig_t ifc;
|
||||
std::vector<ifconfig_t> tmp_ifcs;
|
||||
PIP_ADAPTER_ADDRESSES pAddr = pAddrs;
|
||||
char mac[32] = {'\0'};
|
||||
while (pAddr) {
|
||||
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
pAddr->PhysicalAddress[0],
|
||||
pAddr->PhysicalAddress[1],
|
||||
pAddr->PhysicalAddress[2],
|
||||
pAddr->PhysicalAddress[3],
|
||||
pAddr->PhysicalAddress[4],
|
||||
pAddr->PhysicalAddress[5]);
|
||||
|
||||
memset(&ifc, 0, sizeof(ifc));
|
||||
strncpy(ifc.name, pAddr->AdapterName, sizeof(ifc.name));
|
||||
strncpy(ifc.ip, "0.0.0.0", sizeof(ifc.ip));
|
||||
strncpy(ifc.mask, "255.255.255.255", sizeof(ifc.mask));
|
||||
strncpy(ifc.mac, mac, sizeof(ifc.mac));
|
||||
tmp_ifcs.push_back(ifc);
|
||||
|
||||
pAddr = pAddr->Next;
|
||||
}
|
||||
|
||||
PIP_ADAPTER_INFO pInfo = pInfos;
|
||||
while (pInfo) {
|
||||
for (auto& item : tmp_ifcs) {
|
||||
if (strcmp(item.name, pInfo->AdapterName) == 0) {
|
||||
// description more friendly
|
||||
strncpy(item.name, pInfo->Description, sizeof(item.name));
|
||||
strncpy(item.ip, pInfo->IpAddressList.IpAddress.String, sizeof(item.ip));
|
||||
strncpy(item.mask, pInfo->IpAddressList.IpMask.String, sizeof(item.mask));
|
||||
}
|
||||
}
|
||||
|
||||
pInfo = pInfo->Next;
|
||||
}
|
||||
|
||||
free(pAddrs);
|
||||
free(pInfos);
|
||||
|
||||
// filter
|
||||
ifcs.clear();
|
||||
for (auto& item : tmp_ifcs) {
|
||||
if (strcmp(item.ip, "0.0.0.0") == 0 ||
|
||||
strcmp(item.ip, "127.0.0.1") == 0 ||
|
||||
strcmp(item.mac, "00:00:00:00:00:00") == 0) {
|
||||
continue;
|
||||
}
|
||||
ifcs.push_back(item);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#elif defined(OS_MAC)
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if_dl.h>
|
||||
int ifconfig(std::vector<ifconfig_t>& ifcs) {
|
||||
struct ifaddrs *ifas, *ifap;
|
||||
int ret = getifaddrs(&ifas);
|
||||
if (ret != 0) return ret;
|
||||
ifconfig_s tmp;
|
||||
for (ifap = ifas; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family == AF_INET) {
|
||||
// ipv4
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)ifap->ifa_addr;
|
||||
char* ip = inet_ntoa(addr->sin_addr);
|
||||
// filter
|
||||
if (strcmp(ip, "0.0.0.0") == 0 || strcmp(ip, "127.0.0.1") == 0) {
|
||||
continue;
|
||||
}
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
strncpy(tmp.name, ifap->ifa_name, sizeof(tmp.name));
|
||||
strncpy(tmp.ip, ip, sizeof(tmp.ip));
|
||||
// netmask
|
||||
addr = (struct sockaddr_in*)ifap->ifa_netmask;
|
||||
char* netmask = inet_ntoa(addr->sin_addr);
|
||||
strncpy(tmp.mask, netmask, sizeof(tmp.mask));
|
||||
// broadaddr
|
||||
addr = (struct sockaddr_in*)ifap->ifa_broadaddr;
|
||||
char* broadaddr = inet_ntoa(addr->sin_addr);
|
||||
strncpy(tmp.broadcast, broadaddr, sizeof(tmp.broadcast));
|
||||
// push_back
|
||||
ifcs.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
for (ifap = ifas; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family == AF_LINK) {
|
||||
// hwaddr
|
||||
for (auto iter = ifcs.begin(); iter != ifcs.end(); ++iter) {
|
||||
if (strcmp(iter->name, ifap->ifa_name) == 0) {
|
||||
struct sockaddr_dl* addr = (struct sockaddr_dl*)ifap->ifa_addr;
|
||||
unsigned char* pmac = (unsigned char*)LLADDR(addr);
|
||||
snprintf(iter->mac, sizeof(iter->mac), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
pmac[0], pmac[1], pmac[2], pmac[3], pmac[4], pmac[5]);
|
||||
// filter
|
||||
if (strcmp(iter->mac, "00:00:00:00:00:00") == 0) {
|
||||
ifcs.erase(iter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifas);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int ifconfig(std::vector<ifconfig_t>& ifcs) {
|
||||
return -10; // unimplemented
|
||||
}
|
||||
#endif
|
||||
|
||||
36
third_party/libhv/cpputil/ifconfig.h
vendored
Executable file
36
third_party/libhv/cpputil/ifconfig.h
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
#ifndef HV_IFCONFIG_H_
|
||||
#define HV_IFCONFIG_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "hexport.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "iphlpapi.lib")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
|
||||
typedef struct ifconfig_s {
|
||||
char name[128];
|
||||
char ip[16];
|
||||
char mask[16];
|
||||
char broadcast[16];
|
||||
char mac[20];
|
||||
} ifconfig_t;
|
||||
|
||||
/*
|
||||
* @test
|
||||
std::vector<ifconfig_t> ifcs;
|
||||
ifconfig(ifcs);
|
||||
for (auto& item : ifcs) {
|
||||
printf("%s\nip: %s\nmask: %s\nbroadcast: %s\nmac: %s\n\n",
|
||||
item.name,
|
||||
item.ip,
|
||||
item.mask,
|
||||
item.broadcast,
|
||||
item.mac);
|
||||
}
|
||||
*/
|
||||
HV_EXPORT int ifconfig(std::vector<ifconfig_t>& ifcs);
|
||||
|
||||
#endif // HV_IFCONFIG_H_
|
||||
390
third_party/libhv/cpputil/iniparser.cpp
vendored
Executable file
390
third_party/libhv/cpputil/iniparser.cpp
vendored
Executable file
@@ -0,0 +1,390 @@
|
||||
#include "iniparser.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "hdef.h"
|
||||
#include "herr.h"
|
||||
#include "hstring.h"
|
||||
#include "hfile.h"
|
||||
#include "hbase.h"
|
||||
|
||||
using namespace hv;
|
||||
|
||||
/**********************************
|
||||
# div
|
||||
|
||||
[section]
|
||||
|
||||
key = value # span
|
||||
|
||||
# div
|
||||
***********************************/
|
||||
|
||||
class IniNode {
|
||||
public:
|
||||
enum Type {
|
||||
INI_NODE_TYPE_UNKNOWN,
|
||||
INI_NODE_TYPE_ROOT,
|
||||
INI_NODE_TYPE_SECTION,
|
||||
INI_NODE_TYPE_KEY_VALUE,
|
||||
INI_NODE_TYPE_DIV,
|
||||
INI_NODE_TYPE_SPAN,
|
||||
} type;
|
||||
std::string label; // section|key|comment
|
||||
std::string value;
|
||||
std::list<IniNode*> children;
|
||||
|
||||
virtual ~IniNode() {
|
||||
for (auto pNode : children) {
|
||||
if (pNode) {
|
||||
delete pNode;
|
||||
}
|
||||
}
|
||||
children.clear();
|
||||
}
|
||||
|
||||
void Add(IniNode* pNode) {
|
||||
children.push_back(pNode);
|
||||
}
|
||||
|
||||
void Del(IniNode* pNode) {
|
||||
for (auto iter = children.begin(); iter != children.end(); ++iter) {
|
||||
if ((*iter) == pNode) {
|
||||
delete (*iter);
|
||||
children.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IniNode* Get(const std::string& label, Type type = INI_NODE_TYPE_KEY_VALUE) {
|
||||
for (auto pNode : children) {
|
||||
if (pNode->type == type && pNode->label == label) {
|
||||
return pNode;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class IniSection : public IniNode {
|
||||
public:
|
||||
IniSection() : IniNode(), section(label) {
|
||||
type = INI_NODE_TYPE_SECTION;
|
||||
}
|
||||
std::string §ion;
|
||||
};
|
||||
|
||||
class IniKeyValue : public IniNode {
|
||||
public:
|
||||
IniKeyValue() : IniNode(), key(label) {
|
||||
type = INI_NODE_TYPE_KEY_VALUE;
|
||||
}
|
||||
std::string &key;
|
||||
};
|
||||
|
||||
class IniComment : public IniNode {
|
||||
public:
|
||||
IniComment() : IniNode(), comment(label) {
|
||||
}
|
||||
std::string &comment;
|
||||
};
|
||||
|
||||
IniParser::IniParser() {
|
||||
_comment = DEFAULT_INI_COMMENT;
|
||||
_delim = DEFAULT_INI_DELIM;
|
||||
root_ = NULL;
|
||||
}
|
||||
|
||||
IniParser::~IniParser() {
|
||||
Unload();
|
||||
}
|
||||
|
||||
int IniParser::Unload() {
|
||||
SAFE_DELETE(root_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IniParser::Reload() {
|
||||
return LoadFromFile(_filepath.c_str());
|
||||
}
|
||||
|
||||
int IniParser::LoadFromFile(const char* filepath) {
|
||||
_filepath = filepath;
|
||||
|
||||
HFile file;
|
||||
if (file.open(filepath, "r") != 0) {
|
||||
return ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
std::string str;
|
||||
file.readall(str);
|
||||
const char* c_str = str.c_str();
|
||||
unsigned char utf8_bom[3] = { 0xEF, 0xBB, 0xBF };
|
||||
if (str.size() >= 3 && memcmp(c_str, utf8_bom, 3) == 0) {
|
||||
c_str += 3;
|
||||
}
|
||||
return LoadFromMem(c_str);
|
||||
}
|
||||
|
||||
int IniParser::LoadFromMem(const char* data) {
|
||||
Unload();
|
||||
|
||||
root_ = new IniNode;
|
||||
root_->type = IniNode::INI_NODE_TYPE_ROOT;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << data;
|
||||
std::string strLine;
|
||||
int line = 0;
|
||||
std::string::size_type pos;
|
||||
|
||||
std::string content, comment, strDiv;
|
||||
IniNode* pScopeNode = root_;
|
||||
IniNode* pNewNode = NULL;
|
||||
while (std::getline(ss, strLine)) {
|
||||
++line;
|
||||
|
||||
content = ltrim(strLine);
|
||||
if (content.length() == 0) {
|
||||
// blank line
|
||||
strDiv += '\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
// trim_comment
|
||||
comment = "";
|
||||
pos = content.find_first_of(_comment);
|
||||
if (pos != std::string::npos) {
|
||||
comment = content.substr(pos);
|
||||
content = content.substr(0, pos);
|
||||
}
|
||||
|
||||
content = rtrim(content);
|
||||
if (content.length() == 0) {
|
||||
strDiv += strLine;
|
||||
strDiv += '\n';
|
||||
continue;
|
||||
} else if (strDiv.length() != 0) {
|
||||
IniNode* pNode = new IniNode;
|
||||
pNode->type = IniNode::INI_NODE_TYPE_DIV;
|
||||
pNode->label = strDiv;
|
||||
pScopeNode->Add(pNode);
|
||||
strDiv = "";
|
||||
}
|
||||
|
||||
if (content[0] == '[') {
|
||||
if (content[content.length()-1] == ']') {
|
||||
// section
|
||||
content = trim(content.substr(1, content.length()-2));
|
||||
pNewNode = new IniNode;
|
||||
pNewNode->type = IniNode::INI_NODE_TYPE_SECTION;
|
||||
pNewNode->label = content;
|
||||
root_->Add(pNewNode);
|
||||
pScopeNode = pNewNode;
|
||||
} else {
|
||||
// hlogw("format error, line:%d", line);
|
||||
continue; // ignore
|
||||
}
|
||||
} else {
|
||||
pos = content.find_first_of(_delim);
|
||||
if (pos != std::string::npos) {
|
||||
// key-value
|
||||
pNewNode = new IniNode;
|
||||
pNewNode->type = IniNode::INI_NODE_TYPE_KEY_VALUE;
|
||||
pNewNode->label = trim(content.substr(0, pos));
|
||||
pNewNode->value = trim(content.substr(pos+_delim.length()));
|
||||
pScopeNode->Add(pNewNode);
|
||||
} else {
|
||||
// hlogw("format error, line:%d", line);
|
||||
continue; // ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (comment.length() != 0) {
|
||||
// tail_comment
|
||||
IniNode* pNode = new IniNode;
|
||||
pNode->type = IniNode::INI_NODE_TYPE_SPAN;
|
||||
pNode->label = comment;
|
||||
pNewNode->Add(pNode);
|
||||
comment = "";
|
||||
}
|
||||
}
|
||||
|
||||
// file end comment
|
||||
if (strDiv.length() != 0) {
|
||||
IniNode* pNode = new IniNode;
|
||||
pNode->type = IniNode::INI_NODE_TYPE_DIV;
|
||||
pNode->label = strDiv;
|
||||
root_->Add(pNode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IniParser::DumpString(IniNode* pNode, std::string& str) {
|
||||
if (pNode == NULL) return;
|
||||
|
||||
if (pNode->type != IniNode::INI_NODE_TYPE_SPAN) {
|
||||
if (str.length() > 0 && str[str.length()-1] != '\n') {
|
||||
str += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
switch (pNode->type) {
|
||||
case IniNode::INI_NODE_TYPE_SECTION: {
|
||||
str += '[';
|
||||
str += pNode->label;
|
||||
str += ']';
|
||||
}
|
||||
break;
|
||||
case IniNode::INI_NODE_TYPE_KEY_VALUE: {
|
||||
str += asprintf("%s %s %s", pNode->label.c_str(), _delim.c_str(), pNode->value.c_str());
|
||||
}
|
||||
break;
|
||||
case IniNode::INI_NODE_TYPE_DIV: {
|
||||
str += pNode->label;
|
||||
}
|
||||
break;
|
||||
case IniNode::INI_NODE_TYPE_SPAN: {
|
||||
str += '\t';
|
||||
str += pNode->label;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto p : pNode->children) {
|
||||
DumpString(p, str);
|
||||
}
|
||||
}
|
||||
|
||||
std::string IniParser::DumpString() {
|
||||
std::string str;
|
||||
DumpString(root_, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
int IniParser::Save() {
|
||||
return SaveAs(_filepath.c_str());
|
||||
}
|
||||
|
||||
int IniParser::SaveAs(const char* filepath) {
|
||||
std::string str = DumpString();
|
||||
if (str.length() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HFile file;
|
||||
if (file.open(filepath, "w") != 0) {
|
||||
return ERR_SAVE_FILE;
|
||||
}
|
||||
file.write(str.c_str(), str.length());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<std::string> IniParser::GetSections() {
|
||||
std::list<std::string> ret;
|
||||
if (root_ == NULL) return ret;
|
||||
|
||||
for (auto pNode : root_->children) {
|
||||
if (pNode->type == IniNode::INI_NODE_TYPE_SECTION) {
|
||||
ret.push_back(pNode->label);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::list<std::string> IniParser::GetKeys(const std::string& section) {
|
||||
std::list<std::string> ret;
|
||||
if (root_ == NULL) return ret;
|
||||
|
||||
IniNode* pSection = root_;
|
||||
if (section.length() != 0) {
|
||||
pSection = root_->Get(section, IniNode::INI_NODE_TYPE_SECTION);
|
||||
if (pSection == NULL) return ret;
|
||||
}
|
||||
|
||||
for (auto pNode : pSection->children) {
|
||||
if (pNode->type == IniNode::INI_NODE_TYPE_KEY_VALUE) {
|
||||
ret.push_back(pNode->label);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string IniParser::GetValue(const std::string& key, const std::string& section) {
|
||||
if (root_ == NULL) return "";
|
||||
|
||||
IniNode* pSection = root_;
|
||||
if (section.length() != 0) {
|
||||
pSection = root_->Get(section, IniNode::INI_NODE_TYPE_SECTION);
|
||||
if (pSection == NULL) return "";
|
||||
}
|
||||
|
||||
IniNode* pKV = pSection->Get(key, IniNode::INI_NODE_TYPE_KEY_VALUE);
|
||||
if (pKV == NULL) return "";
|
||||
|
||||
return pKV->value;
|
||||
}
|
||||
|
||||
void IniParser::SetValue(const std::string& key, const std::string& value, const std::string& section) {
|
||||
if (root_ == NULL) {
|
||||
root_ = new IniNode;
|
||||
}
|
||||
|
||||
IniNode* pSection = root_;
|
||||
if (section.length() != 0) {
|
||||
pSection = root_->Get(section, IniNode::INI_NODE_TYPE_SECTION);
|
||||
if (pSection == NULL) {
|
||||
pSection = new IniNode;
|
||||
pSection->type = IniNode::INI_NODE_TYPE_SECTION;
|
||||
pSection->label = section;
|
||||
root_->Add(pSection);
|
||||
}
|
||||
}
|
||||
|
||||
IniNode* pKV = pSection->Get(key, IniNode::INI_NODE_TYPE_KEY_VALUE);
|
||||
if (pKV == NULL) {
|
||||
pKV = new IniNode;
|
||||
pKV->type = IniNode::INI_NODE_TYPE_KEY_VALUE;
|
||||
pKV->label = key;
|
||||
pSection->Add(pKV);
|
||||
}
|
||||
pKV->value = value;
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT bool IniParser::Get(const std::string& key, const std::string& section, bool defvalue) {
|
||||
std::string str = GetValue(key, section);
|
||||
return str.empty() ? defvalue : hv_getboolean(str.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT int IniParser::Get(const std::string& key, const std::string& section, int defvalue) {
|
||||
std::string str = GetValue(key, section);
|
||||
return str.empty() ? defvalue : atoi(str.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT float IniParser::Get(const std::string& key, const std::string& section, float defvalue) {
|
||||
std::string str = GetValue(key, section);
|
||||
return str.empty() ? defvalue : atof(str.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT void IniParser::Set(const std::string& key, const bool& value, const std::string& section) {
|
||||
SetValue(key, value ? "true" : "false", section);
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT void IniParser::Set(const std::string& key, const int& value, const std::string& section) {
|
||||
SetValue(key, asprintf("%d", value), section);
|
||||
}
|
||||
|
||||
template<>
|
||||
HV_EXPORT void IniParser::Set(const std::string& key, const float& value, const std::string& section) {
|
||||
SetValue(key, asprintf("%f", value), section);
|
||||
}
|
||||
53
third_party/libhv/cpputil/iniparser.h
vendored
Executable file
53
third_party/libhv/cpputil/iniparser.h
vendored
Executable file
@@ -0,0 +1,53 @@
|
||||
#ifndef HV_INI_PARSER_H_
|
||||
#define HV_INI_PARSER_H_
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "hexport.h"
|
||||
|
||||
#define DEFAULT_INI_COMMENT "#"
|
||||
#define DEFAULT_INI_DELIM "="
|
||||
|
||||
// fwd
|
||||
class IniNode;
|
||||
|
||||
class HV_EXPORT IniParser {
|
||||
public:
|
||||
IniParser();
|
||||
~IniParser();
|
||||
|
||||
int LoadFromFile(const char* filepath);
|
||||
int LoadFromMem(const char* data);
|
||||
int Unload();
|
||||
int Reload();
|
||||
|
||||
std::string DumpString();
|
||||
int Save();
|
||||
int SaveAs(const char* filepath);
|
||||
|
||||
std::list<std::string> GetSections();
|
||||
std::list<std::string> GetKeys(const std::string& section = "");
|
||||
std::string GetValue(const std::string& key, const std::string& section = "");
|
||||
void SetValue(const std::string& key, const std::string& value, const std::string& section = "");
|
||||
|
||||
// T = [bool, int, float]
|
||||
template<typename T>
|
||||
T Get(const std::string& key, const std::string& section = "", T defvalue = 0);
|
||||
|
||||
// T = [bool, int, float]
|
||||
template<typename T>
|
||||
void Set(const std::string& key, const T& value, const std::string& section = "");
|
||||
|
||||
protected:
|
||||
void DumpString(IniNode* pNode, std::string& str);
|
||||
|
||||
public:
|
||||
std::string _comment;
|
||||
std::string _delim;
|
||||
std::string _filepath;
|
||||
private:
|
||||
IniNode* root_;
|
||||
};
|
||||
|
||||
#endif // HV_INI_PARSER_H_
|
||||
25447
third_party/libhv/cpputil/json.hpp
vendored
Executable file
25447
third_party/libhv/cpputil/json.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
36
third_party/libhv/cpputil/singleton.h
vendored
Executable file
36
third_party/libhv/cpputil/singleton.h
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
#ifndef HV_SINGLETON_H_
|
||||
#define HV_SINGLETON_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#define DISABLE_COPY(Class) \
|
||||
Class(const Class&) = delete; \
|
||||
Class& operator=(const Class&) = delete;
|
||||
|
||||
#define SINGLETON_DECL(Class) \
|
||||
public: \
|
||||
static Class* instance(); \
|
||||
static void exitInstance(); \
|
||||
private: \
|
||||
DISABLE_COPY(Class) \
|
||||
static Class* s_pInstance; \
|
||||
static std::once_flag s_initFlag; \
|
||||
static std::mutex s_mutex;
|
||||
|
||||
#define SINGLETON_IMPL(Class) \
|
||||
Class* Class::s_pInstance = NULL; \
|
||||
std::once_flag Class::s_initFlag; \
|
||||
std::mutex Class::s_mutex; \
|
||||
Class* Class::instance() { \
|
||||
std::call_once(s_initFlag, []() {s_pInstance = new Class;}); \
|
||||
return s_pInstance; \
|
||||
} \
|
||||
void Class::exitInstance() { \
|
||||
std::lock_guard<std::mutex> lock(s_mutex); \
|
||||
if (s_pInstance) { \
|
||||
delete s_pInstance; \
|
||||
s_pInstance = nullptr; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // HV_SINGLETON_H_
|
||||
Reference in New Issue
Block a user