头文件
声明位于include/log4cpp/Priority.hh中
// Priority类提供了重要级别,可以对日志消息进行分类。
class LOG4CPP_EXPORT Priority {
public:
static const int MESSAGE_SIZE; // = 8;
typedef enum {
EMERG = 0,
FATAL = 0,
ALERT = 100,
CRIT = 200,
ERROR = 300,
WARN = 400,
NOTICE = 500,
INFO = 600,
DEBUG = 700,
NOTSET = 800
} PriorityLevel;
typedef int Value;
static const std::string& getPriorityName(int priority) throw();
static Value getPriorityValue(const std::string& priorityName);
};
PriorityLevel
typedef enum {
EMERG = 0,
FATAL = 0,
ALERT = 100,
CRIT = 200,
ERROR = 300,
WARN = 400,
NOTICE = 500,
INFO = 600,
DEBUG = 700,
NOTSET = 800
} PriorityLevel;
- 意义:定义了10个警告级别的常量,每一个常量表示一个警告级别
- 语法说明:它是一个枚举类型,实际上在C++中,它所定义的成员就是一个类的内部变量,相当于直接在Priority这个类中定义了10个整形变量。
- 使用实例:
xxCategory.setPriority(Priority::DEBUG)
typedef int Value;
typedef int Value;
- 语法:定义了一个别名,这样使用Value肯定比int语义更加合理
getPriorityName
static const std::string& getPriorityName(int priority) throw()
这个方法是一个静态方法,并且从名称上我们可以看出,其实这个方法是将一个Value类型的数值转换为人眼可以阅读出的 字符串形式,比getPriorityName(700),那么返回的应该是"DEBUG",我们接下来来看一下他的具体实现:
namespace { // 匿名命名空间
const std::string *names() {
static const std::string priority_names[10] = {
"FATAL",
"ALERT",
"CRIT",
"ERROR",
"WARN",
"NOTICE",
"INFO",
"DEBUG",
"NOTSET",
"UNKNOWN"
};
return priority_names;
}
}
const std::string& Priority::getPriorityName(int priority) throw() {
priority++;
priority /= 100;
return names()[((priority < 0) || (priority > 8)) ? 8 : priority];
}
- 这个算法的逻辑是 只要你规定的priority是小于枚举类型中对应值的,那么都属于所参考的前一个级别
- 这个方法的内部实现利用率一个匿名空间中的priority_names数组,这里用匿名空间可以防止priorityNames的symbol被编译器导出去。是一种比较常用的技术,当我们不想将某些变量定义为类的静态成员变量时就可以使用这种技术
相当于:
getPriorityValue
static Value getPriorityValue(const std::string& priorityName);
也是一个静态方法,从名称可以看到,他是将 优先级名称(警告级别)的人可以阅读的字面值转换为对应的Value类型。实现如下
Priority::Value Priority::getPriorityValue(const std::string& priorityName) {
Priority::Value value = -1;
// 首先从表中进行查找
for (unsigned int i = 0; i < 10; i++) {
if (priorityName == names()[i]) {
value = i * 100;
break;
}
}
if (value == -1) { // 没有找到再看priorityName是否是一个数值字符串
if (priorityName == "EMERG") {
value = 0;
} else {
char* endPointer;
value = std::strtoul(priorityName.c_str(), &endPointer, 10);
if (*endPointer != 0) { //只有他指向的值为0,才表示转换成功
throw std::invalid_argument(
std::string("unknown priority name: '") + priorityName + "'"
);
}
}
}
return value;
}
首先会检测这个字符串是否是常见的字面值字符串,如果是的话,则将对应的警告级别所对应的值返回,比如输入的字符串是"FATAL"则返回的值 是0,如果输入的值是ALERT则返回的值是1.。。。,这一规则正好符合Priority::PriorityLevel中所定义的各个元素所具有的值。 此外,如果输入的是数字,比如"100", “200”…他们会将这些值转换为具体的数值返回,如果输入的不是数字的话,则会抛出invalid_argument异常。
总结
Priority类中定义了两类型,两静态方法
- 两个类型
typedef int Value
typedef enum {DEBUG, ....} PriorityLevel
- 两个静态方法
Value getPriorityValue(const std::string &priorityNameOrNumeric)
◦std::string getPriorityName(Value priorityValue)
Priority就是一个可以提供某些具体日志警告级别的常量,和提供了将权限值和权限字面值相互转换的一个方法。还定义了一个 见名之意的Value类型。