spdlog源码阅读 (3): log_msg和BasicWriter

4. log_msg和它的打手BasicWriter

spdlog源码阅读 (2): sinks的创建和使用中,提到log_msg提供了存储日志的功能。那么到底在spdlog中它是怎么
起到这个作用的呢?
不妨现在代码中搜索下log_msg的具体使用(即在logger_impl.h中),可以得出一下几种用法:

1. log_msg.raw << msg;
2. log_msg.raw.write(fmt, args...);
3. err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol);

上面三行代码是log_msg使用的最几种体现,而做相应操作的raw和formatted是
MemoryWriter类型的对象。

4.1 打手BasicWriter

接上文,继续向上查看MemoryWriter的定义,发现:

typedef BasicMemoryWriter<char> MemoryWriter;

继续查看BasicMemoryWriter:

template <typename Char, typename Allocator = std::allocator<Char> >
class BasicMemoryWriter: public BasicWriter<Char>
//......

在类内部并没有发现我们想要找的"<<"操作符,也没有write。继续向它的父类寻求帮助,
此处打手BasicWriter出现了。

BasicWriter &operator<<(int value)
{
    write_decimal(value);
    return *this;
}

在BasicWriter中,"<<"操作符针对不同参数类型分别提供了对应的实现。打手装备了
武器write_decimal,下面我们就看看这个武器是如何的锋利(叼)。

4.2 打手武器篇

作为程序猿闲话少说,直接代码

template <typename Int>
void write_decimal(Int value)
{
	1. typedef typename internal::IntTraits<Int>::MainType MainType;
	MainType abs_value = static_cast<MainType>(value);
	if (internal::is_negative(value))
	{
	    abs_value = 0 - abs_value;
	    *write_unsigned_decimal(abs_value, 1) = '-';
	}
	else
	{
	    write_unsigned_decimal(abs_value, 0);
	}
}

line1: 使用IntTraits::MainType 定义了一个类型叫MainType,

template <bool FitsIn32Bits>
struct TypeSelector
{
    typedef uint32_t Type;
};

template <>
struct TypeSelector<false>
{
    typedef uint64_t Type;
};

template <typename T>
struct IntTraits
{
    // Smallest of uint32_t and uint64_t that is large enough to represent
    // all values of T.
    typedef typename
    TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
};

在spdlog中这种写法较多,例如判断是否无符号数,通过模板的参数演绎来获取真实的类型。
更多的内容参见(SGI __type_traits)。
write_decimal继续执行调用write_unsigned_decimal通过单独处理10进制下的每一位转换为
字符串,存储到buffer中。

4.3 buffer

在本文示例中,最后的buffer是MemoryBuffer。一般是一个char类型的存储区,默认大小为500字节。
当存储的内容大于该限制时,则进行转储,并扩大空间。扩大的空间每次以当前的缓冲区大小加上,
当前缓冲区的一半。

5 写在最后

关于spdlog的先写到这里,到今天已经有三篇分别介绍: sink,sink的作用,以及日志的缓冲区。
当然实际上spdlog还有更多内容,例如formatter等。后面如果有机会,会整理一个比较完整的类图
放在后面,帮助理解。

(人不是全能的,如果有错误的地方,还请大家不吝指出,本人不胜感激)。

posted @ 2017-03-01 15:18  eskylin的笔记  阅读(1907)  评论(0编辑  收藏  举报