加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
format.hpp 7.73 KB
一键复制 编辑 原始数据 按行查看 历史
刘弘韬 提交于 2024-03-18 10:23 . 上传一下
#ifndef __M_FMT_H__
#define __M_FMT_H__
/*
作用:通过pattern把日志信息输入到流中
方法:
通过_pattern获取对应orders(由于时间的问题,设计成key value)
通过key value 来获取创建 构造对象(FormatItem基类 具体派生)
添加完后后加入到 _items数组中
遍历数组并通过日志信息,完成构建 插入到流中
*/
#include "utils.hpp"
#include "level.hpp"
#include "message.hpp"
#include <memory>
#include <time.h>
#include <vector>
#include <sstream>
namespace logs{
//抽象 格式化子类
class FormatItem{
public:
using ptr = std::shared_ptr<FormatItem>;
virtual void format(std::ostream &out, logs::LogMessage &msg) = 0;
};
//派生 具体的
class MsgFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << msg._playload;
}
};
class LevelFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << logs::LogLevel::toString(msg._level);
}
};
class TimeFormatItem : public FormatItem{
public:
TimeFormatItem(const std::string &fmt = "%H:%M:%S")
:_time_fmt(fmt){}
void format(std::ostream &out, logs::LogMessage &msg) override {
struct tm t;
localtime_r(&msg._ctime, &t);
char temp[32] = {0};
strftime(temp, 31, _time_fmt.c_str(), &t);
out << temp;
}
private:
// 用local_time 和 strftime
std::string _time_fmt;
};
class FileFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << msg._file;
}
};
class LineFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << msg._line;
}
};
class ThreadFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << msg._tid;
}
};
class LoggerFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << msg._logger;
}
};
class TabFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << "\t";
}
};
class NewLineFormatItem : public FormatItem{
public:
void format(std::ostream &out, logs::LogMessage &msg) override {
out << "\n";
}
};
class OtherFormatItem : public FormatItem{
public:
OtherFormatItem(const std::string &str)
:_str(str){}
void format(std::ostream &out, logs::LogMessage &msg) override {
out << _str;
}
private:
std::string _str;
};
/*
%d{子格式} %t线程id %c日志器名称 %f源码文件名 %l源码行号
%T缩进 %p级别 %m消息 %n换行
*/
class Formatter{
public:
using ptr = std::shared_ptr<Formatter>;
Formatter(const std::string& pattern = "[%c|%p]: %d{%Y %D %H:%M:%S} [%t|%f:%l]: %m%n")
:_pattern(pattern){
parsePattern();
}
std::ostream& format(std::ostream& out, logs::LogMessage &msg){
for(auto& it: _items){
it->format(out, msg);
}
return out;
}
std::string format(logs::LogMessage &msg){
std::stringstream ss;
for(auto& it:_items){
it->format(ss, msg);
}
return ss.str();
}
private:
// 根据格式化不同的字符创建不同的格式化子项对象
FormatItem::ptr createItem(const std::string &key,const std::string &value){
if (key == "m") return std::make_shared<MsgFormatItem>();
if (key == "p") return std::make_shared<LevelFormatItem>();
if (key == "c") return std::make_shared<LoggerFormatItem>();
if (key == "t") return std::make_shared<ThreadFormatItem>();
if (key == "n") return std::make_shared<NewLineFormatItem>();
if (key == "d") return std::make_shared<TimeFormatItem>(value);
if (key == "f") return std::make_shared<FileFormatItem>();
if (key == "l") return std::make_shared<LineFormatItem>();
if (key == "T") return std::make_shared<TabFormatItem>();
if (key.empty() == true) return std::make_shared<OtherFormatItem>(value);
std::cout << "format.hpp: %匹配失败" << std::endl;
abort();
return FormatItem::ptr();
}
//对格式化规则字符串解析
bool parsePattern(){
// 用来存储 key 和 value
std::vector<std::pair<std::string,std::string>> fmt_order;
int pos = 0;
std::string key;
std::string value;
while (pos < _pattern.size())
{
// 如果第一个不是%
if(_pattern[pos] != '%'){
value.push_back(_pattern[pos]);
pos++;
continue;
}
// 如果是%
if(_pattern[pos] == '%' && _pattern[pos + 1] == '%'){
value.push_back('%');
pos += 2;
continue;
}
// 如果走完以上两个if 到这里就会是% value有值就是要把其他类型加入到order中
if(value.empty() == false){
fmt_order.push_back(std::make_pair(key,value));
value.clear();
}
// 提取key
pos++;
if(pos < _pattern.size() && std::isalpha(_pattern[pos])){ /*不严谨*/
key.push_back(_pattern[pos]);
pos++;
}
else{
std::cout << "format.hpp :格式化公式格式错误" << std::endl;
return false;
}
// 判断有没有子项
if(pos < _pattern.size() && _pattern[pos] == '{'){
pos++;
bool err_flag = true;
while (pos < _pattern.size()){
if(_pattern[pos] == '}'){
err_flag = false;
pos++;
break;
}
value.push_back(_pattern[pos]);
pos++;
}
if(err_flag == true){
std::cout << "format.hpp :格式化公式子项{}格式错误" << std::endl;
return false;
}
}
fmt_order.push_back(make_pair(key, value));
value.clear();
key.clear();
}
for(auto& order: fmt_order){
_items.push_back(createItem(order.first, order.second));
}
return true;
}
private:
std::string _pattern;
std::vector<FormatItem::ptr> _items;
};
} // namespace logs
#endif
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化