add utilities

This commit is contained in:
gb 2023-02-18 11:26:43 +08:00
parent fbca5468f1
commit baeed0acea
6 changed files with 592 additions and 5 deletions

106
common/cmd.cpp Normal file
View File

@ -0,0 +1,106 @@
#include "cmd.h"
namespace parser
{
static void command_line_to_arguments(const char* cmdl, std::vector<std::string>& args)
{
while(*cmdl)
{
const char* h = cmdl;
while(*h == ' ' || *h == '\t')
h++;
if(*h == 0)
break;
cmdl = h;
if(*h == '\"')
{
cmdl++;
h++;
while(*h)
{
if(*h == '\"')
break;
if(*h == '\\')
h++;
h++;
}
}
else
{
while(*h)
{
if(*h == ' ' || *h == '\t')
break;
h++;
}
}
if(h > cmdl)
args.push_back(std::string(cmdl, h - cmdl));
else if(*h == '\"')
args.push_back("");
if(*h == 0)
break;
cmdl = h + 1;
}
}
}
cmd_line::cmd_line()
{}
cmd_line::~cmd_line()
{}
cmd_line* cmd_line::from_console(const char* tips)
{
std::string in("");
char ch = 0;
if(!tips || *tips == 0)
tips = "input";
printf("%s%s>%s", CONSOLE_COLOR_FRONT_BLUE, tips, CONSOLE_COLOR_NONE);
while((ch = getchar()) != '\n')
in.append(1, ch);
return cmd_line::from_command_line(in.c_str());
}
cmd_line* cmd_line::from_command_line(const char* cmdl)
{
cmd_line* cmd = new cmd_line();
cmd->cmd_line_ = cmdl;
parser::command_line_to_arguments(cmdl, cmd->arguments_);
return cmd;
}
size_t cmd_line::count(void)
{
return arguments_.size();
}
const char* cmd_line::parameter(int ind)
{
if(ind >= 0 && ind < arguments_.size())
return arguments_[ind].c_str();
else
return nullptr;
}
const char* cmd_line::parameter(const char* key)
{
for(int i = 0; i < arguments_.size() - 1; ++i)
{
if(arguments_[i] == key)
return arguments_[i + 1].c_str();
}
return nullptr;
}

92
common/cmd.h Normal file
View File

@ -0,0 +1,92 @@
#pragma once
// command line utility
//
// created on 2023-02-10
//
#include "referer.h"
#include <string>
#include <vector>
#define CONSOLE_COLOR_NONE "\033[0m"
#define CONSOLE_COLOR_FRONT_BLACK "\033[0;30m"
#define CONSOLE_COLOR_FRONT_DARK_GRAY "\033[1;30m"
#define CONSOLE_COLOR_FRONT_RED "\033[0;31m"
#define CONSOLE_COLOR_FRONT_LIGHT_RED "\033[1;31m"
#define CONSOLE_COLOR_FRONT_GREEN "\033[0;32m"
#define CONSOLE_COLOR_FRONT_LIGHT_GREEN "\033[1;32m"
#define CONSOLE_COLOR_FRONT_BROWN "\033[0;33m"
#define CONSOLE_COLOR_FRONT_YELLOW "\033[1;33m"
#define CONSOLE_COLOR_FRONT_BLUE "\033[0;34m"
#define CONSOLE_COLOR_FRONT_LIGHT_BLUE "\033[1;34m"
#define CONSOLE_COLOR_FRONT_PURPLE "\033[0;35m"
#define CONSOLE_COLOR_FRONT_LIGHT_PURPLE "\033[1;35m"
#define CONSOLE_COLOR_FRONT_CYAN "\033[0;36m"
#define CONSOLE_COLOR_FRONT_LIGHT_CYAN "\033[1;36m"
#define CONSOLE_COLOR_FRONT_LIGHT_GRAY "\033[0;37m"
#define CONSOLE_COLOR_FRONT_WHITE "\033[1;37m"
#define CONSOLE_COLOR_BACK_BLACK "\033[0;40m"
#define CONSOLE_COLOR_BACK_DARK_GRAY "\033[1;40m"
#define CONSOLE_COLOR_BACK_RED "\033[0;41m"
#define CONSOLE_COLOR_BACK_LIGHT_RED "\033[1;41m"
#define CONSOLE_COLOR_BACK_GREEN "\033[0;42m"
#define CONSOLE_COLOR_BACK_LIGHT_GREEN "\033[1;42m"
#define CONSOLE_COLOR_BACK_BROWN "\033[0;43m"
#define CONSOLE_COLOR_BACK_YELLOW "\033[1;43m"
#define CONSOLE_COLOR_BACK_BLUE "\033[0;44m"
#define CONSOLE_COLOR_BACK_LIGHT_BLUE "\033[1;44m"
#define CONSOLE_COLOR_BACK_PURPLE "\033[0;45m"
#define CONSOLE_COLOR_BACK_LIGHT_PURPLE "\033[1;45m"
#define CONSOLE_COLOR_BACK_CYAN "\033[0;46m"
#define CONSOLE_COLOR_BACK_LIGHT_CYAN "\033[1;46m"
#define CONSOLE_COLOR_BACK_LIGHT_GRAY "\033[0;47m"
#define CONSOLE_COLOR_BACK_WHITE "\033[1;47m"
namespace console
{
// special effects:
// \033[0m close all attributes
// \033[1m set high-light
// \033[4m underline
// \033[5m blink
// \033[7m reverse(反显)
// \033[8m blanking(消隐)
// \033[30m -- \033[37m set foreground color
// \033[40m -- \033[47m set background color
//
// cursor position:
// \033[nA move up n lines
// \033[nB move down n lines
// \033[nC move right n cols
// \033[nD move left n cols
// \033[y;xH set cursor position
// \033[2J clear screen
// \033[K clear the line after cursor position
// \033[s save cursor position
// \033[u restore cursor position
// \033[?25l hide cursor
// \033[?25h show cursor
};
class cmd_line : public refer
{
std::string cmd_line_;
std::vector<std::string> arguments_;
protected:
cmd_line();
~cmd_line();
public:
static cmd_line* from_console(const char* tips);
static cmd_line* from_command_line(const char* cmdl);
public:
size_t count(void);
const char* parameter(int ind);
const char* parameter(const char* key);
};

View File

@ -311,6 +311,7 @@ int32_t shared_mem::open(int32_t id, size_t* bytes, const char* name)
return errno;
}
log_cls::log(LOG_LEVEL_DEBUG, "shared memory key: %p\n", key);
size = ALIGN_INT(size, shared_mem::page_unit_);
if (!bytes || *bytes != size)
@ -380,7 +381,7 @@ int32_t shared_mem::close(void)
if (first_ && shm_id_ >= 0)
{
ret = log_cls::log_when_err(shmctl(shm_id_, IPC_RMID, nullptr), "shmctrl(IPC_RMID)");
if (ret)
if (ret && ret != ENOENT)
{
// re-map buffer ...
shm_buf_ = (char*)shmat(shm_id_, nullptr, 0);

View File

@ -36,6 +36,8 @@ void log_cls::create_log_file(void)
else
fwrite("\n\n\n", 1, 3, dst_);
}
else
printf("# Failed to create log file(%s): %d(%s)\n", file_.c_str(), errno, strerror(errno));
}
void log_cls::log_internal(const char* txt)
@ -47,7 +49,10 @@ void log_cls::log_internal(const char* txt)
LOCKER locker(lock_);
if (dst_)
{
fwrite(now.c_str(), 1, now.length(), dst_);
size_t wrote = fwrite(now.c_str(), 1, now.length(), dst_);
if(wrote != now.length())
printf("# Write log failed: %d(%s)\n", errno, strerror(errno));
fflush(dst_);
if (ftell(dst_) >= max_size_)
{

View File

@ -1,5 +1,6 @@
#include "referer.h"
#include <iconv.h>
#include "log_util.h"
@ -165,9 +166,17 @@ namespace sys_util
if (para[0].empty())
{
const char* now = getenv("PWD");
bool found = strstr(path, now) == path;
if(found)
{
found = path[strlen(now)] == '/' && strstr(path + strlen(now) + 1, "/") == nullptr;
}
if(found || para[1].empty())
para[1] = path;
return false;
return !found;
}
else
{
@ -210,7 +219,7 @@ namespace sys_util
pid += *id - '0';
id++;
}
if (*id)
if (*id || pid == 0)
return true;
if (cb->process)
@ -284,7 +293,11 @@ namespace sys_util
file += "/";
file += ent->d_name;
if ((ent->d_type & DT_DIR) == 0)
{
file = read_link(file.c_str());
if(file.empty())
file = std::string(dir) + "/" + ent->d_name;
}
if (!on_found(file.c_str(), ent->d_type & DT_DIR, param))
{
ret = 0x5e17;
@ -586,5 +599,347 @@ namespace sys_util
return val;
}
static uint64_t from_dec_str(const char* str, const char** end)
{
uint64_t val = 0;
for(int i = 0; *str && i < 19; ++i, ++str)
{
if(*str >= '0' && *str <= '9')
{
val *= 10;
val += *str - '0';
}
else
break;
}
if(end)
*end = str;
return val;
}
static uint64_t from_oct_str(const char* str, const char** end)
{
uint64_t val = 0;
for(int i = 0; *str && i < 21; ++i, ++str)
{
if(*str >= '0' && *str <= '7')
{
val *= 8;
val += *str - '0';
}
else
break;
}
if(end)
*end = str;
return val;
}
static uint64_t from_bin_str(const char* str, const char** end)
{
uint64_t val = 0;
for(int i = 0; *str && i < 64; ++i, ++str)
{
if(*str >= '0' && *str <= '1')
{
val *= 2;
val += *str - '0';
}
else
break;
}
if(end)
*end = str;
return val;
}
uint64_t to_int(const char* str, const char** end)
{
if(!str || *str == 0)
{
if(end)
*end = str;
return 0;
}
if(strstr(str, "0x") == str)
return from_hex_str(str + 2, end);
if(str[strlen(str) - 1] == 'h' || str[strlen(str) - 1] == 'H')
return from_hex_str(str, end);
if(str[strlen(str) - 1] == 'o' || str[strlen(str) - 1] == 'O')
return from_oct_str(str, end);
if(str[strlen(str) - 1] == 'b' || str[strlen(str) - 1] == 'B')
return from_bin_str(str, end);
bool hex = false;
for(int i = 0; str[i]; ++i)
{
if(str[i] < '0')
break;
if(str[i] > '9')
{
if((str[i] >= 'a' && str[i] <= 'f') ||
(str[i] >= 'A' && str[i] <= 'F'))
hex = true;
break;
}
}
return hex ? from_hex_str(str, end) : from_dec_str(str, end);
}
/* iconv_open language options:
Europe:
ASCII, ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16}, KOI8-R, KOI8-U, KOI8-RU,
CP{1250,1251,1252,1253,1254,1257}, CP{850,866},
Mac{Roman,CentralEurope,Iceland,Croatian,Romania},
Mac{Cyrillic,Ukraine,Greek,Turkish}, Macintosh
Semitic:
ISO-8859-{6,8}, CP{1255,1256}, CP862, Mac{Hebrew,Arabic}
Janpanese:
EUC-JP, SHIFT-JIS, CP932, ISO-2022-JP, ISO-2022-JP-2, ISO-2022-JP-1
Chinese:
EUC-CN, HZ, GBK, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS, ISO-2022-CN, ISO-2022-CN-EXT
Korean:
EUC-KR, CP949, ISO-2022-KR, JOHAB
Armenian:
ARMSCII-8
Georgian:
Georgian-Academy, Georgian-PS
Thai:
TIS-620, CP874, MacThai
Laos:
MuleLao-1, CP1133
Vietnam:
VISCII, TCVN, CP1258
Special:
HP-ROMAN8, NEXTSTEP
Full Unicode:
UTF-8
UCS-2, UCS-2BE, UCS-2LE
UCS-4, UCS-4BE, UCS-4LE
UTF-16, UTF-16BE, UTF-16LE
UTF-32, UTF-32BE, UTF-32LE
UTF-7
JAVA
*/
std::string transform_between_gbk_and_utf8(const char* in, bool to_utf8, int *err)
{
size_t len = strlen(in) + 8, ol = len * 2;
char *buf = (char*)malloc(len), *oper = buf, *out = nullptr, *oper1 = nullptr;
iconv_t conv;
memset(buf, 0, len);
strcpy(buf, in);
if(to_utf8)
conv = iconv_open("UTF-8", "GBK");
else
conv = iconv_open("GBK", "UTF-8");
if(conv == (iconv_t)-1)
{
if(err)
*err = errno;
free(buf);
return "";
}
oper1 = out = (char*)malloc(ol);
memset(out, 0, ol);
len -= 8;
if(iconv(conv, &oper, &len, &oper1, &ol))
{
if(err)
*err = errno;
}
else if(err)
*err = 0;
std::string ret(out);
free(buf);
free(out);
iconv_close(conv);
return std::move(ret);
}
std::string transform_between_utf16_and_utf8(const char* in, size_t bytes, bool to_utf8)
{
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
std::string ret("");
if(to_utf8)
{
unsigned short *uc = *(unsigned short**)&in, val = 0;
for(size_t i = 0; i < bytes / 2; ++i, ++uc)
{
val = *uc;
if ((*uc>=0xDC00 && *uc<=0xDFFF) || *uc==0) break; /* check for invalid. */
if (*uc>=0xD800 && *uc<=0xDBFF) /* UTF16 surrogate pairs. */
{
unsigned short uc2 = uc[1];
if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */
val = 0x10000 + (((*uc & 0x3FF) << 10) | (uc2 & 0x3FF));
}
int len = 4;
char buf[4] = {0}, *ptr2 = buf;
if (val<0x80) len=1;else if (val<0x800) len=2;else if (val<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((val | 0x80) & 0xBF); val >>= 6;
case 3: *--ptr2 =((val | 0x80) & 0xBF); val >>= 6;
case 2: *--ptr2 =((val | 0x80) & 0xBF); val >>= 6;
case 1: *--ptr2 =(val | firstByteMark[len]);
}
ret += std::string(buf, len);
}
}
else
{
char* unic = (char*)malloc(strlen(in) * 3 + 8);
unsigned char * cur = (unsigned char*)unic;
while (*cur = *in++)
{
if ((*cur & 0x0f0) == 0x0e0)
{
if (((unsigned char)in[0] & 0x0c0) == 0x80 &&
((unsigned char)in[1] & 0x0c0) == 0x80)
{
char* hex = "0123456789ABCDEF";
unsigned short us = *cur & 0x0f;
us <<= 6;
us += in[0] & 0x3f;
us <<= 6;
us += in[1] & 0x3f;
*cur++ = '\\';
*cur++ = 'u';
cur[3] = hex[us & 0x0f];
us >>= 4;
cur[2] = hex[us & 0x0f];
us >>= 4;
cur[1] = hex[us & 0x0f];
us >>= 4;
cur[0] = hex[us & 0x0f];
cur += 3;
in += 2;
}
}
cur++;
}
*cur++ = 0;
ret = std::string(unic, (char*)cur - unic);
free(unic);
}
return std::move(ret);
}
std::string to_abs_path(const char* base, const char* rel_path)
{
if(*rel_path == '/')
return rel_path;
std::string b(base), r(rel_path);
size_t pos = 0;
while(b.length() && b[b.length() - 1] == '/')
b.erase(b.length() - 1);
while(r[0] == '.')
{
if(r[1] == '/')
r.erase(0, 2);
else if(r[1] == '.' && r[2] == '/')
{
pos = b.rfind('/');
if(pos == std::string::npos)
break;
b.erase(pos);
r.erase(0, 3);
}
else
break;
}
b += "/" + r;
return std::move(b);
}
std::string to_rel_path(const char* base, const char* abs_path)
{
if(*abs_path != '/')
return abs_path;
std::string rel(""), b(base), a(abs_path);
size_t pos = 0;
while(b.length() && b[b.length() - 1] == '/')
b.erase(b.length() - 1);
while(a.find(b) == std::string::npos)
{
rel += "../";
pos = b.rfind('/');
if(pos == 0)
break;
b.erase(pos - 1);
}
if(rel.empty())
rel = "./";
return std::move(rel + a);
}
const char* pick_simple_block(const char* head, char end)
{
const char* tail = head + 1;
int cnt = 1;
while(*tail)
{
if(*tail == end)
{
cnt--;
if(cnt == 0)
break;
}
else if(*tail == *head)
{
cnt++;
}
else if(*tail == '\\')
{
tail++;
if(*tail == 0)
break;
}
tail++;
}
return cnt == 0 ? tail : nullptr;
}
}

View File

@ -173,4 +173,32 @@ namespace sys_util
bool trim_left(std::string& str, const char* space = " \t");
bool trim_right(std::string& str, const char* space = " \t");
uint64_t from_hex_str(const char* hex, const char** end = nullptr); // convert 0x100 to 256. parameter 'end' to receive the stopped position
// Function: convert number string to integer, support hex, dec, oct and bin
//
// Parameter: str - number string.
// 0x.../...h: as hexadecimal
// ...o: as octonary
// ...b: as binary
// ...: as decimal, or as hexadecimal if has hex letter
//
// end - to receive the ending point when covert over
//
// Return: integer, default is ZERO, you should check the ending point when this value returned
uint64_t to_int(const char* str, const char** end = nullptr);
std::string transform_between_gbk_and_utf8(const char* in, bool to_utf8, int* err = nullptr);
std::string transform_between_utf16_and_utf8(const char* in, size_t bytes, bool to_utf8);
std::string to_abs_path(const char* base, const char* rel_path);
std::string to_rel_path(const char* base, const char* abs_path);
// Function: pick simple block in pair chars
//
// Parameter: head - beginning of the string, and the first character is the beginning char
//
// end - ending character of the block
//
// Return: the last positoin of the block (*ret = end), or nullptr if not matched
const char* pick_simple_block(const char* head, char end);
}