FixedBuffer和logstream

class FixedBuffer:noncopyable
{
};
class logstream:noncopyable
{
};

先说一下包含的头文件有一个StringPiece.h

个人感觉这个stringpiece没有必要实现啊,直接用std::string就好了
内部实现的操作,基本上std::string都能完成.后面有关stringpiece我都直接放弃了
const char* data() const { return ptr_; }
int size() const { return length_; }
bool empty() const { return length_ == 0; }
const char* begin() const { return ptr_; }
const char* end() const { return ptr_ + length_; }

void clear() { ptr_ = NULL; length_ = 0; }
void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; }
下面是作者原话:

A string like object that points into another piece of memory.
 Useful for providing an interface that allows clients to easily
 pass in either a "const char*" or a "string".
 Arghh! I wish C++ literals were automatically of type "string".

FixedBuffer作用:

FixedBuffer类:实现了对于一块字符数组的管理
成员变量:
用char m_data[SIZE]保存数据
用char* m_cur记录当前操作的那个元素的指针,默认指向最后一个字符的下一个位置.

字符数组示意图 SIZE=8
m_data:['1']['2']['3']['4']['\0']['\0']['\0']['\0']
            m_cur:4            end:8
因此
length() = 4 =m_cur-m_data
sizeof m_data == 8 ==SIZE
end() == m_data+ sizeof m_data
avail() == end()-m_cur

FixedBuffer成员变量:

private:
void (*m_cookie)(); //一个函数指针,暂时未知作用
char m_data[SIZE]; //最重要的成员,字符数组
char* m_cur; //便于操作字符数组的指针

FixedBuffer成员函数:

public:
FixedBuffer():m_cur(m_data)
{
setCookie(cookieStart);
}
~FixedBuffer()
{
setCookie(cookieEnd);
}
//拷贝一段字符放到字符数组m_data中
void append(const char* buf,size_t len)
{
//只有当剩余元素够用时才进行拷贝
if(implicit_cast<size_t>(avail())>len)
{
memcpy(m_cur,buf,len);
m_cur+=len;
}
}
//返回内部字符串
const char* data() const{return m_data;}
//得到内部字符串的大小,也就是m_data数据长度
int length() const{return static_cast<int>(m_cur-m_data);} //返回m_cur指针
char* current(){return m_cur;} //得到字符数组剩余可用字符
int avail() const{return static_cast<int>(end()-m_cur);} //更改m_cur位置
void add(size_t len){m_cur+=len;} //让m_cur回到初始m_data位置
void reset(){m_cur=m_data;} //清空内部字符数组
void bzero(){memZero(m_data,sizeof(m_data));} //为了GDB使用,返回m_data到m_cur之间的数据
const char* debugString()
{
m_cur='\0';
return m_data;
} void setCookie(void (*cookie)()){m_cookie=cookie;} //为了单元测试使用
string toString() const{return string(m_data,length());}
//StringPiece已放弃使用
//StringPiece toStringPiece() const; private:
const char* end() const{return m_data+sizeof(m_data);}
//都暂时没有实现,以后会实现
static void cookieStart(){}
static void cookieEnd(){}

需要注意一下,源码中作者提供了两个FixedBuffer大小

const int kSmallBuffer=4000;
const int kLargeBuffer=4000*1000;

template class FixedBuffer<kSmallBuffer>;
template class FixedBuffer<kLargeBuffer>;

logstream作用:

logstream 类:
数据成员只有一个,就是上面的FixedBuffer<4000>;
成员函数:
基本上就是重载了一大堆<<操作符,可以实现把各种基本的数据类型保存到内部m_buffer中

logstream成员变量:

private:
typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;
Buffer m_buffer;//内部数据成员,类型是FixedBuffer<4000>

logstream成员函数:

    typedef logstream self; //省字数
public:
//Buffer类型其实就是一个FixedBuffer,大小为4000的类型
typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;
//重载了一堆<<操作符,可以实现针对各种基本/常用数据类型的logstream << 操作
//很多<<重载的实现都依赖于formatInteger函数
self& operator<<(bool v)
{
m_buffer.append(v?"":"",);
return *this;
}
self& operator<<(short);
self& operator<<(unsigned short);
self& operator<<(int);
self& operator<<(unsigned int);
self& operator<<(long);
self& operator<<(unsigned long);
self& operator<<(long long);
self& operator<<(unsigned long long);
self& operator<<(const void*);
self& operator<<(float v)
{
*this<<static_cast<double>(v);
return *this;
}
self& operator<<(double);
self& operator<<(char v)
{
m_buffer.append(&v,);
return *this;
}
self& operator<<(const char* str)
{
if(str)
m_buffer.append(str,strlen(str));
else
m_buffer.append("(null)",);
return *this;
}
self& operator<<(const unsigned char* str)
{
*this<<reinterpret_cast<const char*>(str);
return *this;
}
self& operator<<(const string& v)
{
m_buffer.append(v.data(),v.size());
return *this;
}
//self& operator<<(const StringPiece& v);废弃掉不用
self& operator<<(const Buffer& v)
{
m_buffer.append(v.data(),v.length());
return *this;
} //一些基本操作,添加数据,返回FixedBuffer<4000>,重置m_buffer
void append(const char* data,int len);
const Buffer& buffer() const{return m_buffer;}
void resetBuffer(){m_buffer.reset();} private:
//用于静态编译时的一些断言
void staticCheck();
//很重要的一个函数,用于实现向m_buffer中append各种类型
template<typename T>
void formatInteger(T);

测试:

#include"base/logstream.h"
#include<iostream>
using namespace std; namespace mymuduo{
namespace currentthread {
void cacheTid()
{
}
}
} int main()
{
//内部数据(字符数组)大小只有4000
mymuduo::logstream ls;
bool b=false;
short s=;
int i=;
unsigned long ul=;
double d=3.123456;
string str("nmsl");
mymuduo::logstream::Buffer buffer;
buffer.append("nmsl2",); ls<<b<<" "<<s<<" "<<i<<" "<<ul<<" "
<<d<<" "<<str.data()<<" "<<buffer; std::cout<<ls.buffer().data()<<std::endl; }

打印结果:

0 23 133 10000000 3.123456 nmsl nmsl2

只要明白了logstream内部是如何存储数据的,就不难理解logstream的实现了,logstream就是封装了一堆

<<操作符,用于保存不同数据类型的数据。

内部存储数据通过FixedBuufer<4000>来实现,而FixedBuufer<4000>又是通过char data[4000]来实现的,

因此只需要搞明白对char[]的基本操作就可以了。

muduo源码解析10-logstream类的更多相关文章

  1. muduo源码解析5-mutex相关类

    mutexlock和mutexlockguard class mutexlock:noncopyable { }: class mutexlockguard:noncopyable { }: 作用: ...

  2. AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍

    AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...

  3. Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了

    这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...

  4. muduo源码解析11-logger类

    logger: class logger { }; 在说这个logger类之前,先看1个关键的内部类 Impl private: //logger内部数据实现类Impl,内部含有以下成员变量 //时间 ...

  5. Netty源码解析 -- 内存对齐类SizeClasses

    在学习Netty内存池之前,我们先了解一下Netty的内存对齐类SizeClasses,它为Netty内存池中的内存块提供大小对齐,索引计算等服务方法. 源码分析基于Netty 4.1.52 Nett ...

  6. AOP源码解析:AspectJExpressionPointcutAdvisor类

    先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...

  7. java源码解析之Object类

    一.Object类概述   Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解   Object的方法可以分成两类,一类是被关键字fin ...

  8. Bulma 源码解析之 .columns 类

    {说明} 这一部分的源码内容被我简化了,另外我还额外添加了一个辅助类 is-grow. .columns // 修饰类 &.is-centered justify-content: cente ...

  9. java源码解析之String类(二)

    上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...

随机推荐

  1. break statement not within loop or switch报错

    break statement not within loop or switch. 注意你的循环,可能多加了个分号.for语句后面?

  2. checkbox变成单选型

    checkbox的特性是可以选中或者取消,有时需要利用这一点做一个类似radio的选项框: <input type="checkbox" class="aa&quo ...

  3. 高阶NumPy知识图谱-《利用Python进行数据分析》

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片. 其他章 ...

  4. PHP array_shift() 函数

    实例 删除数组中的第一个元素(red),并返回被删除的元素: <?php $a=array("a"=>"red","b"=> ...

  5. vue_shop(基于vue电商管理后台网站)

    vue_shop 目录 vue_shop day01 实现登录功能 项目预开发处理 Login.vue完整代码: 处理步骤: 添加element-ui的表单组件 添加第三方字体: 添加表单验证 导入a ...

  6. intel:spectre&Meltdown侧信道攻击(五)—— DRAM address mapping

    前面介绍了row hammer,理论上很完美,实际操作的时候会面临很尴尬的问题:内存存储数据最小的单位是cell(就是个电容,充电是1,放电是0),无数个横着的cell组成row,无数个竖着的cell ...

  7. org.hibernate.AssertionFailure: null id 错误

    对象属性有Blob类型: 而Blob需在输入流中读取: InputStream in = new FileInputStream(url.getFile()); Blob bookPic = lobH ...

  8. JAVA编程中你一定要掌握的“快捷键”

    JAVA编程常用快捷键 相信很多编程小白刚开始的时候,看向大神的时候都是双膝跪地满眼泪水的膜拜之情~不因为别的,就是因为他们可以随随便便敲出很多行代码,而且他们没有动鼠标!这时候就有人问了:“怎么才能 ...

  9. python8.1多线程

    import threadingimport time def run1 (name,sex): print(name,sex,"执行线程1") time.sleep(3)def ...

  10. 《Python测试开发技术栈—巴哥职场进化记》—软件测试工程师“兵器库”

    上文<Python测试开发技术栈-巴哥职场进化记>-初来乍到,请多关照 我们介绍了巴哥入职后见到了自己的导师华哥,第一次参加团队站会,认识了团队中的开发小哥哥和产品小姐姐以及吃到了公司的加 ...