dev 1.0.5windows
This commit is contained in:
parent
a12cee77f1
commit
fb1ff82d96
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,8 +1,9 @@
|
|||||||
*
|
*
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!doc.md
|
||||||
!README.txt
|
!README.txt
|
||||||
!version.txt
|
!version.txt
|
||||||
!doc.md
|
!CMakeList.txt
|
||||||
!*/
|
!*/
|
||||||
!include/*
|
!include/*
|
||||||
!doc/*
|
!doc/*
|
||||||
|
155
include/iini.h
155
include/iini.h
@ -1,19 +1,13 @@
|
|||||||
#ifndef _IINI_H_
|
#ifndef _IINI_H_
|
||||||
#define _IINI_H_
|
#define _IINI_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "sysenv.h"
|
#include "sysenv.h"
|
||||||
#if _OS_WIN
|
#if _OS_WIN
|
||||||
#ifndef strcasecmp
|
|
||||||
#define strcasecmp _stricmp
|
|
||||||
#endif
|
|
||||||
#ifndef strncasecmp
|
|
||||||
#define strncasecmp _strnicmp
|
|
||||||
#endif
|
|
||||||
#elif _OS_LINUX
|
#elif _OS_LINUX
|
||||||
#include <strings.h>
|
|
||||||
#else
|
#else
|
||||||
#error "Not Supported Operator System"
|
#error "Not Supported Operator System"
|
||||||
#endif
|
#endif
|
||||||
@ -22,154 +16,13 @@
|
|||||||
#define INICHAR char
|
#define INICHAR char
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined INI_BUFFER_SIZE
|
|
||||||
#define INI_BUFFER_SIZE 512
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ini_get_str(const INICHAR* filename, const INICHAR* section, const INICHAR* key,
|
int ini_get_str(const INICHAR* filename, const INICHAR* section, const INICHAR* key,
|
||||||
const INICHAR* def_vaule, INICHAR* buf, size_t szbuf);
|
const INICHAR* def_vaule, INICHAR* buf, size_t szbuf);
|
||||||
|
|
||||||
static inline INICHAR* _ini_skip_leading(const INICHAR* str)
|
|
||||||
{
|
|
||||||
assert(str != NULL);
|
|
||||||
while ('\0' < *str && *str <= ' ')
|
|
||||||
str++;
|
|
||||||
return (INICHAR*)str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline INICHAR* _ini_skip_trailing(const INICHAR* str, const INICHAR* base)
|
|
||||||
{
|
|
||||||
assert(str != NULL);
|
|
||||||
assert(base != NULL);
|
|
||||||
while (str > base && '\0' < *(str - 1) && *(str - 1) <= ' ')
|
|
||||||
str--;
|
|
||||||
return (INICHAR*)str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static INICHAR* _ini_str_skip_trailing(INICHAR* str)
|
|
||||||
{
|
|
||||||
INICHAR* ptr = _ini_skip_trailing(strchr(str, '\0'), str);
|
|
||||||
assert(ptr != NULL);
|
|
||||||
*ptr = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _ini_clean_string(INICHAR** start_pptr, INICHAR** end_pptr) {
|
|
||||||
/* Remove a trailing comment */
|
|
||||||
int is_string = 0;
|
|
||||||
*start_pptr = _ini_skip_leading(*end_pptr + 1);
|
|
||||||
for (*end_pptr = *start_pptr; **end_pptr != '#' && **end_pptr != ';' && **end_pptr != '\0'; *end_pptr += 1) {
|
|
||||||
if (**end_pptr == '"') {
|
|
||||||
if (*(*end_pptr + 1) == '"') {
|
|
||||||
*end_pptr += 1; /* skip "" (both quotes) */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
is_string = !is_string;/* single quote, toggle isstring */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*(*end_pptr) == '\\' && *(*end_pptr + 1) == '"') {
|
|
||||||
*end_pptr += 1; /* skip \" (both quotes */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
**end_pptr = ' ';
|
|
||||||
*end_pptr = _ini_skip_trailing(*end_pptr, *start_pptr);
|
|
||||||
**end_pptr = '\0';
|
|
||||||
|
|
||||||
/* Remove double quotes surrounding a value */
|
|
||||||
if (**start_pptr == '"' && *(*end_pptr - 1) == '"') {
|
|
||||||
*end_pptr -= 1;
|
|
||||||
*start_pptr += 1;
|
|
||||||
**end_pptr = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int _ini_str_get_section(INICHAR **start_pptr, INICHAR **end_pptr,
|
|
||||||
INICHAR* buf, size_t szbuf) {
|
|
||||||
*start_pptr = _ini_skip_leading(buf);
|
|
||||||
*end_pptr = strchr(buf, ']');
|
|
||||||
if (**start_pptr != '[' || *end_pptr == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* When arrived here, a section was found; now optionally skip leading and
|
|
||||||
* trailing whitespace.
|
|
||||||
*/
|
|
||||||
assert(*start_pptr != NULL && **start_pptr == '[');
|
|
||||||
*start_pptr = _ini_skip_leading(*start_pptr + 1);
|
|
||||||
assert(*end_pptr != NULL && **end_pptr == ']');
|
|
||||||
*end_pptr = _ini_skip_trailing(*end_pptr, *start_pptr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int _ini_str_get_key(INICHAR** start_pptr, INICHAR** end_pptr,
|
|
||||||
INICHAR* buf, size_t szbuf) {
|
|
||||||
*start_pptr = _ini_skip_leading(buf);
|
|
||||||
if (**start_pptr == '[' || **start_pptr == '#' || **start_pptr == ':') return -1;
|
|
||||||
|
|
||||||
*end_pptr = strchr(*start_pptr, '='); /* Parse out the equal sign */
|
|
||||||
if (*end_pptr == NULL) *end_pptr = strchr(*start_pptr, ':');
|
|
||||||
if (*end_pptr == NULL) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _int_get_all_string(FILE* fp, const INICHAR* section, const INICHAR* key,
|
|
||||||
int idx_section, int idx_key, INICHAR* buf, size_t szbuf) {
|
|
||||||
int len = 0, idx = 0;
|
|
||||||
INICHAR* start_ptr, * end_ptr;
|
|
||||||
INICHAR local_buf[INI_BUFFER_SIZE] = { 0 };
|
|
||||||
|
|
||||||
assert(fp != NULL);
|
|
||||||
len = (section != NULL) ? (int)strlen(section) : 0;
|
|
||||||
/* Move through file 1 line at a time until a section is matched or EOF. If
|
|
||||||
* parameter Section is NULL, only look at keys above the first section. If
|
|
||||||
* idxSection is positive, copy the relevant section name.
|
|
||||||
*/
|
|
||||||
if (len > 0 || idx_section >= 0) {
|
|
||||||
assert(idx_section >= 0 || section != NULL);
|
|
||||||
idx = -1;
|
|
||||||
do {
|
|
||||||
if (fgets(local_buf, INI_BUFFER_SIZE, fp) == NULL) return -1;
|
|
||||||
if (_ini_str_get_section(&start_ptr, &end_ptr, local_buf, INI_BUFFER_SIZE) != 0) continue;
|
|
||||||
} while (!((int)(end_ptr - start_ptr) == len && section != NULL && strncasecmp(start_ptr, section, len) == 0));
|
|
||||||
}
|
|
||||||
/* Now that the section has been found, find the entry.
|
|
||||||
* Stop searching upon leaving the section's area.
|
|
||||||
*/
|
|
||||||
assert(key != NULL || idx_key >= 0);
|
|
||||||
len = (key != NULL) ? (int)strlen(key) : 0;
|
|
||||||
idx = -1;
|
|
||||||
do {
|
|
||||||
if (fgets(local_buf, INI_BUFFER_SIZE, fp) == NULL) return -1;
|
|
||||||
if (_ini_str_get_key(&start_ptr, &end_ptr, local_buf, INI_BUFFER_SIZE) != 0) continue;
|
|
||||||
} while (len != 0 && strncasecmp(start_ptr, key, len) != 0);
|
|
||||||
|
|
||||||
_ini_clean_string(&start_ptr, &end_ptr);
|
|
||||||
/* Copy up to BufferSize chars to buffer */
|
|
||||||
strncpy(buf, start_ptr, szbuf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ini_get_str(const INICHAR* filename, const INICHAR* section, const INICHAR* key,
|
|
||||||
const INICHAR* def_vaule, INICHAR* buf, size_t szbuf) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
int res = -1;
|
|
||||||
|
|
||||||
if (fp = fopen(filename, "rb")) {
|
|
||||||
res = _int_get_all_string(fp, section, key, -1, -1, buf, szbuf);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
strncpy(buf, ((def_vaule == NULL) ? (const char*)"" : def_vaule), szbuf);
|
|
||||||
buf[szbuf] = '\0';
|
|
||||||
}
|
|
||||||
res = strlen(buf);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
203
include/llog.h
203
include/llog.h
@ -1,13 +1,19 @@
|
|||||||
#ifndef _LLOG_H_
|
#ifndef _LLOG_H_
|
||||||
#define _LLOG_H_
|
#define _LLOG_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <time.h>
|
#include "sysenv.h"
|
||||||
|
#if _OS_WIN
|
||||||
|
|
||||||
|
#elif _OS_LINUX
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Not Supported Operator System"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef uint16_t log_mask_t;
|
typedef uint16_t log_mask_t;
|
||||||
|
|
||||||
#define LOG_MASK_ENDLINE (1 << 0)
|
#define LOG_MASK_ENDLINE (1 << 0)
|
||||||
@ -46,25 +52,6 @@ extern "C" {
|
|||||||
|
|
||||||
enum { _LOG_TRACE, _LOG_DEBUG, _LOG_INFO, _LOG_WARN, _LOG_ERROR, _LOG_FATAL };
|
enum { _LOG_TRACE, _LOG_DEBUG, _LOG_INFO, _LOG_WARN, _LOG_ERROR, _LOG_FATAL };
|
||||||
|
|
||||||
static const char* _log_level_strings[] = {
|
|
||||||
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LOG_COLOR(code) \033[##code##m
|
|
||||||
#define LOG_COLOR_TRACE LOG_COLOR(94)
|
|
||||||
#define LOG_COLOR_DEBUG LOG_COLOR(36)
|
|
||||||
#define LOG_COLOR_INFO LOG_COLOR(32)
|
|
||||||
#define LOG_COLOR_WARN LOG_COLOR(33)
|
|
||||||
#define LOG_COLOR_ERROR LOG_COLOR(31)
|
|
||||||
#define LOG_COLOR_FATAL LOG_COLOR(35)
|
|
||||||
|
|
||||||
#define _TO_STR(str) #str
|
|
||||||
#define TO_STR(str) _TO_STR(str)
|
|
||||||
static const char* _log_level_colors[] = {
|
|
||||||
TO_STR(LOG_COLOR_TRACE), TO_STR(LOG_COLOR_DEBUG), TO_STR(LOG_COLOR_INFO),
|
|
||||||
TO_STR(LOG_COLOR_WARN), TO_STR(LOG_COLOR_ERROR), TO_STR(LOG_COLOR_FATAL)
|
|
||||||
};
|
|
||||||
|
|
||||||
#define log_head_trace( log, szlog) log_fill_head_str(_LOG_TRACE, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
#define log_head_trace( log, szlog) log_fill_head_str(_LOG_TRACE, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
||||||
#define log_head_debug( log, szlog) log_fill_head_str(_LOG_DEBUG, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
#define log_head_debug( log, szlog) log_fill_head_str(_LOG_DEBUG, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
||||||
#define log_head_info( log, szlog) log_fill_head_str(_LOG_INFO, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
#define log_head_info( log, szlog) log_fill_head_str(_LOG_INFO, log, szlog, LOG_MASK_BASE_DEFAULT, __FILE__, __func__, __func__, __LINE__)
|
||||||
@ -81,156 +68,34 @@ static const char* _log_level_colors[] = {
|
|||||||
#define log_head_fatal_ex( log, szlog, mode, mask) log_fill_head_str(_LOG_FATAL, log, szlog, mask, __FILE__, mode, __func__, __LINE__)
|
#define log_head_fatal_ex( log, szlog, mode, mask) log_fill_head_str(_LOG_FATAL, log, szlog, mask, __FILE__, mode, __func__, __LINE__)
|
||||||
#define log_head_ex(level, log, szlog, mode, mask) log_fill_head_str(level , log, szlog, mask, __FILE__, mode, __func__, __LINE__)
|
#define log_head_ex(level, log, szlog, mode, mask) log_fill_head_str(level , log, szlog, mask, __FILE__, mode, __func__, __LINE__)
|
||||||
|
|
||||||
#define _LOG_MAX_HEAD_BUF_SIZE 256
|
|
||||||
|
|
||||||
struct _fill_head_parm {
|
size_t log_fill_head_str(int level, char* log, size_t szlog,
|
||||||
int level;
|
log_mask_t mask, const char* file, const char* mode, const char* func, int line);
|
||||||
char* buf;
|
|
||||||
size_t szbuf;
|
|
||||||
log_mask_t mask;
|
|
||||||
const char* file;
|
|
||||||
const char* mode;
|
|
||||||
const char* func;
|
|
||||||
int line;
|
|
||||||
|
|
||||||
struct tm* time;
|
|
||||||
};
|
|
||||||
|
|
||||||
static size_t _log_fill_head_time_ymd(struct _fill_head_parm* parm) {
|
|
||||||
log_mask_t mask = parm->mask;
|
|
||||||
char* buf = parm->buf;
|
|
||||||
size_t szbuf = parm->szbuf;
|
|
||||||
struct tm* time = parm->time;
|
|
||||||
if (LOG_MASK_TIME_YMD & mask) {
|
|
||||||
if (LOG_MASK_YEAR & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, "%Y", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, "Y");
|
|
||||||
}
|
|
||||||
if (LOG_MASK_MONTH & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, "-%m", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, "-M");
|
|
||||||
}
|
|
||||||
if (LOG_MASK_DAY & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, "-%d", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, "-D");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return szbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t _log_fill_head_time_hms(struct _fill_head_parm* parm) {
|
|
||||||
log_mask_t mask = parm->mask;
|
|
||||||
char* buf = parm->buf;
|
|
||||||
size_t szbuf = parm->szbuf;
|
|
||||||
struct tm* time = parm->time;
|
|
||||||
if (LOG_MASK_TIME_HMS & mask) {
|
|
||||||
if (LOG_MASK_HOUR & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, "%H", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, "h");
|
|
||||||
}
|
|
||||||
if (LOG_MASK_MINUTE & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, ":%M", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, ":m");
|
|
||||||
}
|
|
||||||
if (LOG_MASK_SECOND & mask) {
|
|
||||||
szbuf += strftime(buf + szbuf, _LOG_MAX_HEAD_BUF_SIZE - szbuf, ":%S", time);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, ":s");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return szbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static size_t _log_fill_head_detail(struct _fill_head_parm* parm) {
|
|
||||||
log_mask_t mask = parm->mask;
|
|
||||||
char* buf = parm->buf;
|
|
||||||
size_t szbuf = parm->szbuf;
|
|
||||||
int file_offset = 0;
|
|
||||||
|
|
||||||
if (LOG_MASK_COLORS & mask) {
|
|
||||||
szbuf += sprintf(buf + szbuf, "%s%-5s\033[0m \033[90m",
|
|
||||||
_log_level_colors[parm->level],
|
|
||||||
(LOG_MASK_LEVEL & mask) ? _log_level_strings[parm->level] : "nan");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
szbuf += sprintf(buf + szbuf, "%-5s ",
|
|
||||||
(LOG_MASK_LEVEL & mask) ? _log_level_strings[parm->level] : "nan");
|
|
||||||
}
|
|
||||||
if (LOG_FILE_SIMPLE & mask) {
|
|
||||||
for (file_offset = strlen(parm->file);
|
|
||||||
file_offset > -1; file_offset -= 1) {
|
|
||||||
if (parm->file[file_offset] == '/' || parm->file[file_offset] == '\\') {
|
|
||||||
file_offset += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
szbuf += sprintf(buf + szbuf, "%.128s:%.32s:%.32s:%d:",
|
|
||||||
(LOG_MASK_FILE & mask) ? parm->file + file_offset : "file",
|
|
||||||
(LOG_MASK_MODE & mask) ? parm->mode : "mode",
|
|
||||||
(LOG_MASK_FUNC & mask) ? parm->func : "func",
|
|
||||||
(LOG_MASK_LINE & mask) ? parm->line : 0);
|
|
||||||
|
|
||||||
if (LOG_MASK_COLORS & mask) {
|
|
||||||
szbuf += sprintf(buf + szbuf, "\033[0m");
|
|
||||||
}
|
|
||||||
return szbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t log_fill_head_str(int level, char* log, size_t szlog,
|
|
||||||
log_mask_t mask, const char* file, const char* mode, const char* func, int line) {
|
|
||||||
size_t szbuf = 0;
|
|
||||||
char buf[_LOG_MAX_HEAD_BUF_SIZE] = { 0 };
|
|
||||||
|
|
||||||
time_t t = time(NULL);
|
|
||||||
struct tm* time = localtime(&t);
|
|
||||||
struct _fill_head_parm parm = {
|
|
||||||
.level = level,
|
|
||||||
.buf = buf,
|
|
||||||
.szbuf = 0,
|
|
||||||
.mask = mask,
|
|
||||||
.file = file,
|
|
||||||
.mode = mode,
|
|
||||||
.func = func,
|
|
||||||
.line = line,
|
|
||||||
|
|
||||||
.time = time
|
|
||||||
};
|
|
||||||
size_t(*callback[3])(struct _fill_head_parm* parm) = {
|
|
||||||
_log_fill_head_time_ymd,
|
|
||||||
_log_fill_head_time_hms,
|
|
||||||
_log_fill_head_detail
|
|
||||||
};
|
|
||||||
for (int i = 0; i < sizeof(callback) / sizeof(callback[0]); i++) {
|
|
||||||
szbuf += (*callback[i])(&parm);
|
|
||||||
parm.buf[szbuf] = '|';
|
|
||||||
parm.szbuf = szbuf + 1;
|
|
||||||
}
|
|
||||||
if (LOG_MASK_ENDLINE & mask) szbuf += sprintf(buf, "\n");
|
|
||||||
buf[szbuf] = '\0';
|
|
||||||
szbuf += 1;
|
|
||||||
if (szlog <= szbuf) return 0;
|
|
||||||
strncpy(log, buf, szbuf);
|
|
||||||
return szbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void log_buf(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 rxi
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#endif /* _LLOG_H_ */
|
#endif /* _LLOG_H_ */
|
0
src/fifo.c
Normal file
0
src/fifo.c
Normal file
157
src/ini.c
Normal file
157
src/ini.c
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#include <iini.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if _OS_WIN
|
||||||
|
|
||||||
|
#elif _OS_LINUX
|
||||||
|
#include <strings.h>
|
||||||
|
#else
|
||||||
|
#error "Not Supported Operator System"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef strcasecmp
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#endif
|
||||||
|
#ifndef strncasecmp
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INI_BUFFER_SIZE 512
|
||||||
|
|
||||||
|
inline INICHAR* _ini_skip_leading(const INICHAR* str)
|
||||||
|
{
|
||||||
|
assert(str != NULL);
|
||||||
|
while ('\0' < *str && *str <= ' ')
|
||||||
|
str++;
|
||||||
|
return (INICHAR*)str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline INICHAR* _ini_skip_trailing(const INICHAR* str, const INICHAR* base)
|
||||||
|
{
|
||||||
|
assert(str != NULL);
|
||||||
|
assert(base != NULL);
|
||||||
|
while (str > base && '\0' < *(str - 1) && *(str - 1) <= ' ')
|
||||||
|
str--;
|
||||||
|
return (INICHAR*)str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline INICHAR* _ini_str_skip_trailing(INICHAR* str)
|
||||||
|
{
|
||||||
|
INICHAR* ptr = _ini_skip_trailing(strchr(str, '\0'), str);
|
||||||
|
assert(ptr != NULL);
|
||||||
|
*ptr = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ini_clean_string(INICHAR** start_pptr, INICHAR** end_pptr) {
|
||||||
|
/* Remove a trailing comment */
|
||||||
|
int is_string = 0;
|
||||||
|
*start_pptr = _ini_skip_leading(*end_pptr + 1);
|
||||||
|
for (*end_pptr = *start_pptr; **end_pptr != '#' && **end_pptr != ';' && **end_pptr != '\0'; *end_pptr += 1) {
|
||||||
|
if (**end_pptr == '"') {
|
||||||
|
if (*(*end_pptr + 1) == '"') {
|
||||||
|
*end_pptr += 1; /* skip "" (both quotes) */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_string = !is_string;/* single quote, toggle isstring */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*(*end_pptr) == '\\' && *(*end_pptr + 1) == '"') {
|
||||||
|
*end_pptr += 1; /* skip \" (both quotes */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
**end_pptr = ' ';
|
||||||
|
*end_pptr = _ini_skip_trailing(*end_pptr, *start_pptr);
|
||||||
|
**end_pptr = '\0';
|
||||||
|
|
||||||
|
/* Remove double quotes surrounding a value */
|
||||||
|
if (**start_pptr == '"' && *(*end_pptr - 1) == '"') {
|
||||||
|
*end_pptr -= 1;
|
||||||
|
*start_pptr += 1;
|
||||||
|
**end_pptr = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ini_str_get_section(INICHAR** start_pptr, INICHAR** end_pptr,
|
||||||
|
INICHAR* buf, size_t szbuf) {
|
||||||
|
*start_pptr = _ini_skip_leading(buf);
|
||||||
|
*end_pptr = strchr(buf, ']');
|
||||||
|
if (**start_pptr != '[' || *end_pptr == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* When arrived here, a section was found; now optionally skip leading and
|
||||||
|
* trailing whitespace.
|
||||||
|
*/
|
||||||
|
assert(*start_pptr != NULL && **start_pptr == '[');
|
||||||
|
*start_pptr = _ini_skip_leading(*start_pptr + 1);
|
||||||
|
assert(*end_pptr != NULL && **end_pptr == ']');
|
||||||
|
*end_pptr = _ini_skip_trailing(*end_pptr, *start_pptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ini_str_get_key(INICHAR** start_pptr, INICHAR** end_pptr,
|
||||||
|
INICHAR* buf, size_t szbuf) {
|
||||||
|
*start_pptr = _ini_skip_leading(buf);
|
||||||
|
if (**start_pptr == '[' || **start_pptr == '#' || **start_pptr == ':') return -1;
|
||||||
|
|
||||||
|
*end_pptr = strchr(*start_pptr, '='); /* Parse out the equal sign */
|
||||||
|
if (*end_pptr == NULL) *end_pptr = strchr(*start_pptr, ':');
|
||||||
|
if (*end_pptr == NULL) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _int_get_all_string(FILE* fp, const INICHAR* section, const INICHAR* key,
|
||||||
|
int idx_section, int idx_key, INICHAR* buf, size_t szbuf) {
|
||||||
|
int len = 0, idx = 0;
|
||||||
|
INICHAR* start_ptr, * end_ptr;
|
||||||
|
INICHAR local_buf[INI_BUFFER_SIZE] = { 0 };
|
||||||
|
|
||||||
|
assert(fp != NULL);
|
||||||
|
len = (section != NULL) ? (int)strlen(section) : 0;
|
||||||
|
/* Move through file 1 line at a time until a section is matched or EOF. If
|
||||||
|
* parameter Section is NULL, only look at keys above the first section. If
|
||||||
|
* idxSection is positive, copy the relevant section name.
|
||||||
|
*/
|
||||||
|
if (len > 0 || idx_section >= 0) {
|
||||||
|
assert(idx_section >= 0 || section != NULL);
|
||||||
|
idx = -1;
|
||||||
|
do {
|
||||||
|
if (fgets(local_buf, INI_BUFFER_SIZE, fp) == NULL) return -1;
|
||||||
|
if (_ini_str_get_section(&start_ptr, &end_ptr, local_buf, INI_BUFFER_SIZE) != 0) continue;
|
||||||
|
} while (!((int)(end_ptr - start_ptr) == len && section != NULL && strncasecmp(start_ptr, section, len) == 0));
|
||||||
|
}
|
||||||
|
/* Now that the section has been found, find the entry.
|
||||||
|
* Stop searching upon leaving the section's area.
|
||||||
|
*/
|
||||||
|
assert(key != NULL || idx_key >= 0);
|
||||||
|
len = (key != NULL) ? (int)strlen(key) : 0;
|
||||||
|
idx = -1;
|
||||||
|
do {
|
||||||
|
if (fgets(local_buf, INI_BUFFER_SIZE, fp) == NULL) return -1;
|
||||||
|
if (_ini_str_get_key(&start_ptr, &end_ptr, local_buf, INI_BUFFER_SIZE) != 0) continue;
|
||||||
|
} while (len != 0 && strncasecmp(start_ptr, key, len) != 0);
|
||||||
|
|
||||||
|
_ini_clean_string(&start_ptr, &end_ptr);
|
||||||
|
/* Copy up to BufferSize chars to buffer */
|
||||||
|
strncpy(buf, start_ptr, szbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ini_get_str(const INICHAR* filename, const INICHAR* section, const INICHAR* key,
|
||||||
|
const INICHAR* def_vaule, INICHAR* buf, size_t szbuf) {
|
||||||
|
FILE* fp = NULL;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
if (fp = fopen(filename, "rb")) {
|
||||||
|
res = _int_get_all_string(fp, section, key, -1, -1, buf, szbuf);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
strncpy(buf, ((def_vaule == NULL) ? (const char*)"" : def_vaule), szbuf);
|
||||||
|
buf[szbuf] = '\0';
|
||||||
|
}
|
||||||
|
res = strlen(buf);
|
||||||
|
return res;
|
||||||
|
}
|
171
src/log.c
Normal file
171
src/log.c
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include <llog.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define LOG_COLOR(code) \033[##code##m
|
||||||
|
#define LOG_COLOR_TRACE LOG_COLOR(94)
|
||||||
|
#define LOG_COLOR_DEBUG LOG_COLOR(36)
|
||||||
|
#define LOG_COLOR_INFO LOG_COLOR(32)
|
||||||
|
#define LOG_COLOR_WARN LOG_COLOR(33)
|
||||||
|
#define LOG_COLOR_ERROR LOG_COLOR(31)
|
||||||
|
#define LOG_COLOR_FATAL LOG_COLOR(35)
|
||||||
|
|
||||||
|
#define LOG_MAX_HEAD_BUF_SIZE 256
|
||||||
|
|
||||||
|
#define _TO_STR(str) #str
|
||||||
|
#define TO_STR(str) _TO_STR(str)
|
||||||
|
|
||||||
|
static const char* _log_level_strings[] = {
|
||||||
|
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* _log_level_colors[] = {
|
||||||
|
TO_STR(LOG_COLOR_TRACE), TO_STR(LOG_COLOR_DEBUG), TO_STR(LOG_COLOR_INFO),
|
||||||
|
TO_STR(LOG_COLOR_WARN), TO_STR(LOG_COLOR_ERROR), TO_STR(LOG_COLOR_FATAL)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _fill_head_parm {
|
||||||
|
int level;
|
||||||
|
char* buf;
|
||||||
|
size_t szbuf;
|
||||||
|
log_mask_t mask;
|
||||||
|
const char* file;
|
||||||
|
const char* mode;
|
||||||
|
const char* func;
|
||||||
|
int line;
|
||||||
|
|
||||||
|
struct tm* time;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t _log_fill_head_time_ymd(struct _fill_head_parm* parm) {
|
||||||
|
log_mask_t mask = parm->mask;
|
||||||
|
char* buf = parm->buf;
|
||||||
|
size_t szbuf = parm->szbuf;
|
||||||
|
struct tm* time = parm->time;
|
||||||
|
if (LOG_MASK_TIME_YMD & mask) {
|
||||||
|
if (LOG_MASK_YEAR & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, "%Y", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, "Y");
|
||||||
|
}
|
||||||
|
if (LOG_MASK_MONTH & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, "-%m", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, "-M");
|
||||||
|
}
|
||||||
|
if (LOG_MASK_DAY & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, "-%d", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, "-D");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return szbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _log_fill_head_time_hms(struct _fill_head_parm* parm) {
|
||||||
|
log_mask_t mask = parm->mask;
|
||||||
|
char* buf = parm->buf;
|
||||||
|
size_t szbuf = parm->szbuf;
|
||||||
|
struct tm* time = parm->time;
|
||||||
|
if (LOG_MASK_TIME_HMS & mask) {
|
||||||
|
if (LOG_MASK_HOUR & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, "%H", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, "h");
|
||||||
|
}
|
||||||
|
if (LOG_MASK_MINUTE & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, ":%M", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, ":m");
|
||||||
|
}
|
||||||
|
if (LOG_MASK_SECOND & mask) {
|
||||||
|
szbuf += strftime(buf + szbuf, LOG_MAX_HEAD_BUF_SIZE - szbuf, ":%S", time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, ":s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return szbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t _log_fill_head_detail(struct _fill_head_parm* parm) {
|
||||||
|
log_mask_t mask = parm->mask;
|
||||||
|
char* buf = parm->buf;
|
||||||
|
size_t szbuf = parm->szbuf;
|
||||||
|
int file_offset = 0;
|
||||||
|
|
||||||
|
if (LOG_MASK_COLORS & mask) {
|
||||||
|
szbuf += sprintf(buf + szbuf, "%s%-5s\033[0m \033[90m",
|
||||||
|
_log_level_colors[parm->level],
|
||||||
|
(LOG_MASK_LEVEL & mask) ? _log_level_strings[parm->level] : "nan");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
szbuf += sprintf(buf + szbuf, "%-5s ",
|
||||||
|
(LOG_MASK_LEVEL & mask) ? _log_level_strings[parm->level] : "nan");
|
||||||
|
}
|
||||||
|
if (LOG_FILE_SIMPLE & mask) {
|
||||||
|
for (file_offset = strlen(parm->file);
|
||||||
|
file_offset > -1; file_offset -= 1) {
|
||||||
|
if (parm->file[file_offset] == '/' || parm->file[file_offset] == '\\') {
|
||||||
|
file_offset += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
szbuf += sprintf(buf + szbuf, "%.128s:%.32s:%.32s:%d:",
|
||||||
|
(LOG_MASK_FILE & mask) ? parm->file + file_offset : "file",
|
||||||
|
(LOG_MASK_MODE & mask) ? parm->mode : "mode",
|
||||||
|
(LOG_MASK_FUNC & mask) ? parm->func : "func",
|
||||||
|
(LOG_MASK_LINE & mask) ? parm->line : 0);
|
||||||
|
|
||||||
|
if (LOG_MASK_COLORS & mask) {
|
||||||
|
szbuf += sprintf(buf + szbuf, "\033[0m");
|
||||||
|
}
|
||||||
|
return szbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t log_fill_head_str(int level, char* log, size_t szlog,
|
||||||
|
log_mask_t mask, const char* file, const char* mode, const char* func, int line) {
|
||||||
|
size_t szbuf = 0;
|
||||||
|
char buf[LOG_MAX_HEAD_BUF_SIZE] = { 0 };
|
||||||
|
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm* time = localtime(&t);
|
||||||
|
struct _fill_head_parm parm = {
|
||||||
|
.level = level,
|
||||||
|
.buf = buf,
|
||||||
|
.szbuf = 0,
|
||||||
|
.mask = mask,
|
||||||
|
.file = file,
|
||||||
|
.mode = mode,
|
||||||
|
.func = func,
|
||||||
|
.line = line,
|
||||||
|
|
||||||
|
.time = time
|
||||||
|
};
|
||||||
|
size_t(*callback[3])(struct _fill_head_parm* parm) = {
|
||||||
|
_log_fill_head_time_ymd,
|
||||||
|
_log_fill_head_time_hms,
|
||||||
|
_log_fill_head_detail
|
||||||
|
};
|
||||||
|
for (int i = 0; i < sizeof(callback) / sizeof(callback[0]); i++) {
|
||||||
|
szbuf += (*callback[i])(&parm);
|
||||||
|
parm.buf[szbuf] = '|';
|
||||||
|
parm.szbuf = szbuf + 1;
|
||||||
|
}
|
||||||
|
if (LOG_MASK_ENDLINE & mask) szbuf += sprintf(buf, "\n");
|
||||||
|
buf[szbuf] = '\0';
|
||||||
|
szbuf += 1;
|
||||||
|
if (szlog <= szbuf) return 0;
|
||||||
|
strncpy(log, buf, szbuf);
|
||||||
|
return szbuf;
|
||||||
|
}
|
0
src/mempool.c
Normal file
0
src/mempool.c
Normal file
0
src/rbtree.c
Normal file
0
src/rbtree.c
Normal file
@ -2,9 +2,13 @@ cmake_minimum_required(VERSION 3.22.1)
|
|||||||
|
|
||||||
project(proj)
|
project(proj)
|
||||||
|
|
||||||
set(EXECUTABLE_OUTPUT_PATH ../)
|
set(EXECUTABLE_OUTPUT_PATH ../../)
|
||||||
add_subdirectory(server_proj server_proj)
|
set(C_STANDARD 99)
|
||||||
add_subdirectory(client_proj client_proj)
|
set(C_STANDARD_REQUIRED TRUE)
|
||||||
|
set(C_EXTENSIONS FALSE)
|
||||||
|
|
||||||
|
add_subdirectory(server_proj server)
|
||||||
|
add_subdirectory(client_proj client)
|
||||||
|
add_subdirectory(../../ zzylib)
|
||||||
# cmake ..
|
# cmake ..
|
||||||
# cmake --build .
|
# cmake --build .
|
@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.22.1)
|
|||||||
|
|
||||||
project(client_proj)
|
project(client_proj)
|
||||||
|
|
||||||
set(EXECUTABLE_OUTPUT_PATH ../../)
|
set(C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(C_STANDARD_REQUIRED TRUE)
|
||||||
|
set(C_EXTENSIONS FALSE)
|
||||||
include_directories(../../../include)
|
|
||||||
add_executable(client_proj client_proj.c)
|
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} client_proj.c)
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC ../../../include)
|
||||||
|
target_link_libraries(${PROJECT_NAME} zzylib)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} wsock32 ws2_32)
|
target_link_libraries(${PROJECT_NAME} wsock32 ws2_32)
|
||||||
endif()
|
endif()
|
||||||
|
@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.22.1)
|
|||||||
|
|
||||||
project(server_proj)
|
project(server_proj)
|
||||||
|
|
||||||
set(EXECUTABLE_OUTPUT_PATH ../../)
|
set(C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(C_STANDARD_REQUIRED TRUE)
|
||||||
|
set(C_EXTENSIONS FALSE)
|
||||||
include_directories(../../../include)
|
|
||||||
add_executable(server_proj server_proj.c)
|
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} server_proj.c)
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC ../../../include)
|
||||||
|
target_link_libraries(${PROJECT_NAME} zzylib)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} wsock32 ws2_32)
|
target_link_libraries(${PROJECT_NAME} wsock32 ws2_32)
|
||||||
endif()
|
endif()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user