a8/a8/strutils.cc
aozhiwei 399eed8bd8 1
2022-12-27 08:30:18 +08:00

478 lines
15 KiB
C++

#include <string.h>
#include <assert.h>
#include <a8/a8.h>
#include <a8/strutils.h>
namespace a8
{
std::string Bin2Hex(const std::string& binstr)
{
std::string result;
for(unsigned int i = 0; i < binstr.size(); i++){
assert(false);
}
return result;
}
const char* GetValidStr1(const char* szLine, char **pp, int& iLen, const char* szIngore)
{
//skip ingorechars
*pp = (char*)szLine;
while(*pp && **pp && strchr(szIngore, **pp)) (*pp)++;
//read validchars
iLen = 0;
while((*pp + iLen) && *(*pp + iLen) && !strchr(szIngore, *(*pp + iLen++))) ;
if (!strchr(szIngore, *(*pp + iLen))){
iLen--;
}
return *pp + iLen ;
}
std::string GetValidStr(const std::string& strLine, std::string& strVal, const char* szIngore)
{
char *pp = NULL;
int iLen = 0;
const char *result = a8::GetValidStr1(strLine.c_str(), &pp, iLen, szIngore);
strVal.assign(pp, iLen);
return result ? std::string(result) : "";
}
std::string Trim(const std::string& str)
{
std::string text = str;
if(!text.empty()){
text.erase(0, text.find_first_not_of(" \n\r\t"));
text.erase(text.find_last_not_of(" \n\r\t") + 1);
}
return text;
}
std::string FormatEx(const char* fmt, std::initializer_list<a8::XValue>& args)
{
std::string result;
result.reserve(1024);
const char *p = fmt;
auto itr = args.begin();
while(*p){
if(*p == '%' && *(p+1)){
p++;
switch(*p){
case 'd':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
case 'f':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
case 's':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
default:{
result.push_back('%');
result.push_back(*p);
}
}
}else{
result.push_back(*p);
}
p++;
}
return result;
}
std::string Format(const char* fmt, std::initializer_list<a8::XValue> args)
{
return a8::FormatEx(fmt, args);
}
std::string FormatEx2(const char* fmt, std::vector<a8::XValue>& args)
{
std::string result;
result.reserve(1024);
const char *p = fmt;
auto itr = args.begin();
while(*p){
if(*p == '%' && *(p+1)){
p++;
switch(*p){
case 'd':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
case 'f':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
case 's':
assert(itr != args.end());
result.append(itr->GetString().c_str());
itr++;
break;
default:{
result.push_back('%');
result.push_back(*p);
}
}
}else{
result.push_back(*p);
}
p++;
}
return result;
}
std::string Format2(const char* fmt, std::vector<a8::XValue> args)
{
return a8::FormatEx2(fmt, args);
}
void Split(const std::string& str, std::vector<std::string>& list, char separator)
{
const char *p = str.c_str();
const char *pv = p;
while(*p){
if(*p == separator){
if(p > pv){
list.push_back(std::string(pv, p - pv));
}else{
list.push_back("");
}
pv = p + 1;
}
p++;
}
if(*p == separator){
list.push_back("");
}else if(p > pv){
list.push_back(std::string(pv, p - pv));
}
}
unsigned char FromHex(unsigned char x)
{
return isdigit(x) ? x-'0' : x-'A'+10;
}
unsigned char ToHex(unsigned char x)
{
return x > 9 ? x + 55 : x + 48;
}
std::string HexEncode(const std::string& str)
{
std::string strTemp;
strTemp.reserve(str.size() * 2);
for (unsigned int i = 0; i < str.size(); i++) {
char buf[3] = {'\0'};
sprintf(buf, "%x", (int)str[i]);
strTemp += std::string(strTemp);
}
return strTemp;
}
bool HexDecode(const std::string& str, std::string& outstr)
{
for (unsigned int i = 0; i + 1 < str.size(); i += 2) {
int int_c = 0;
char buf[3] = {str[i], str[i + 1], '\0'};
sscanf(buf, "%x", &int_c);
outstr.push_back((char)int_c);
}
return str.size() % 2 == 0;
}
std::string UrlEncode(const std::string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++) {
if (isalnum((unsigned char)str[i]) ||
(str[i] == '-') ||
(str[i] == '_') ||
(str[i] == '.') ||
(str[i] == '~')) {
strTemp += str[i];
} else if (str[i] == ' ') {
strTemp += "+";
} else {
strTemp += '%';
strTemp += ToHex((unsigned char)str[i] >> 4);
strTemp += ToHex((unsigned char)str[i] % 16);
}
}
return strTemp;
}
std::string UrlDecode(const std::string &sIn)
{
std::string sOut;
for(unsigned int i = 0; i < sIn.size(); i++ ){
unsigned char ch = 0;
if(sIn[i] == '%'){
ch = (a8::FromHex(sIn[i + 1]) << 4);
ch |= a8::FromHex(sIn[i + 2]);
i += 2;
}else if(sIn[i] == '+'){
ch = ' ';
}
else{
ch = sIn[i];
}
sOut += (char)ch;
}
return sOut;
}
void ParserQueryStr(char* buf, std::string& url, std::string& querystr)
{
char *p_query_start = strstr(buf, "?");
if (p_query_start) {
url.assign(buf, p_query_start - buf);
p_query_start++;
char *p_query_end = strstr(p_query_start, " ");
if (p_query_end) {
querystr.assign(p_query_start, p_query_end - p_query_start);
} else {
querystr.assign(p_query_start);
}
} else {
p_query_start = buf;
char *p_end = strstr(p_query_start, " ");
if (p_end) {
url.assign(p_query_start, p_end - p_query_start);
} else {
url.assign(p_query_start);
}
}
}
void ParserUrlQueryString(const char* querystring, std::map<std::string, a8::XValue>& query)
{
if(!querystring || *querystring == 0){
return;
}
std::vector<std::string> params;
a8::Split(std::string(querystring), params, '&');
for(unsigned int i = 0; i < params.size(); i++){
int pos = params[i].find('=');
if(pos > 0){
std::string key = params[i].substr(0, pos);
std::string val = params[i].substr(pos + 1, params[i].size() - pos);
val = a8::UrlDecode(val);
// query[key] = a8::XValue(val);
query.insert(std::pair<std::string, a8::XValue>(key, a8::XValue(val)));
}
}
}
void ReplaceString(std::string& basestr, const std::string& srcstr, const std::string& deststr)
{
std::string::size_type pos = 0;
std::string::size_type srcLen = srcstr.size();
std::string::size_type desLen = deststr.size();
pos = basestr.find(srcstr, pos);
while((pos != std::string::npos)){
basestr.replace(pos, srcLen, deststr);
pos = basestr.find(srcstr, (pos + desLen));
}
}
std::string HttpResponse(const std::string& content)
{
return HttpResponse(200, content);
}
std::string HttpResponse(int code, const std::string& content)
{
std::string response = a8::Format(
"HTTP/1.1 %d OK\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: %d\r\n\r\n%s",
{
code,
content.size(),
content
});
return response;
}
std::string JsonEscapeString(const std::string& str)
{
std::string result;
result.reserve(str.size() * 2);
const char* p = str.data();
while(*p){
if(*p >=0 && *p < ' '){
switch(*p){
case '\b':
result.append("\\b");
break;
case '\t':
result.append("\\t");
break;
case '\n':
result.append("\\n");
break;
case '\f':
result.append("\\f");
break;
case '\r':
result.append("\\r");
break;
default:
{
char unicodehex[6] = {'\\', 'u', '0', '0', '0', '0'};
char *pu = &unicodehex[5];
int n = *p;
do{
*pu-- = "0123456789abcdef"[n % 16];
n /= 16;
}while(n);
result.append(unicodehex);
}
}
}else if (*p == '"'){
result.append("\\\"");
}else if (*p == '\\'){
result.append("\\\\");
}else{
result.push_back(*p);
}//end if
p++;
}
return result;
}
std::string IntToFixedString(int val, int n)
{
if (n < 1 || n > 10) {
abort();
}
char buf_fmt[20];
sprintf(buf_fmt, "%%%dd", n);
char buf[20];
sprintf(buf, buf_fmt, val);
std::string result = std::string((char*)buf);
a8::ReplaceString(result, " ", "0");
return result;
}
bool ReadStringFromFile(const std::string& filename, std::string& data)
{
FILE *fp = fopen(filename.c_str(), "rb");
if (!fp) {
return false;
}
fseek(fp, 0, SEEK_END);
int fileSize = ftell(fp);
if(fileSize){
char *p = (char*)malloc(fileSize + 1);
if(p){
*(p + fileSize) = '\0';
fseek(fp, 0, SEEK_SET);
fread(p, 1, fileSize, fp);
if (fileSize > 0) {
data.append(p, fileSize);
}
free(p);
}
}
fclose(fp);
return true;
}
int SafeStrCmp(const char* s1, const char* s2)
{
return strcmp(s1 ? s1 : "", s2 ? s2 : "");
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
size_t GetUtf8Length(const char *str)
{
static unsigned char utf8_look_for_table[] =
{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};
#define UTFLEN(x) utf8_look_for_table[(x)]
auto utf8_char_len =
[] (char firstByte) -> int
{
const unsigned char kFirstBitMask = 128; // 1000000
const unsigned char kSecondBitMask = 64; // 0100000
const unsigned char kThirdBitMask = 32; // 0010000
const unsigned char kFourthBitMask = 16; // 0001000
const unsigned char kFifthBitMask = 8; // 0000100
std::string::difference_type offset = 1;
if (firstByte & kFirstBitMask) { // This means the first byte has a value greater than 127, and so is beyond the ASCII range.
if (firstByte & kThirdBitMask) { // This means that the first byte has a value greater than 224, and so it must be at least a three-octet code point.
if (firstByte & kFourthBitMask) { // This means that the first byte has a value greater than 240, and so it must be a four-octet code point.
offset = 4;
}else{
offset = 3;
}
}else{
offset = 2;
}
}
return offset;
};
int clen = strlen(str);
int len = 0;
for (const char *ptr = str;
*ptr!=0&&len<clen;
len++, ptr+=UTFLEN((unsigned char)*ptr)) ;
return len;
}
#pragma GCC diagnostic pop
std::string CopyString(const std::string& str)
{
std::string result;
result += str;
return result;
}
std::string CopyString(const char* str)
{
std::string result(str);
return result;
}
}