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. Python元组运算符

    Python元组运算符: len(元组名): 返回元组对象的长度 # len(元组名): # 返回元组对象的长度 tuple_1 = (1,4,5,2,3,6) print(len(tuple_1)) ...

  2. Python os.tcsetpgrp() 方法

    概述 os.tcsetpgrp() 方法用于设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg.高佣联盟 www.cgewang.com 语法 tcsetpgrp()方 ...

  3. PHP registerXPathNamespace() 函数

    实例 为下一个 XPath 查询创建命名空间上下文: <?php$xml=<<<XML高佣联盟 www.cgewang.com<book xmlns:chap=" ...

  4. Java自学-JDBC 数据库连接池

    数据库连接池 与线程池类似的,数据库也有一个数据库连接池. 不过他们的实现思路是不一样的. 本章节讲解了自定义数据库连接池类:ConnectionPool,虽然不是很完善和健壮,但是足以帮助大家理解C ...

  5. CentOS7系统管理与运维实战

    CentOS7系统管理与运维实战 下载地址 https://pan.baidu.com/s/1KFHVI-XjGaLMrh39WuhyCw 扫码下面二维码关注公众号回复100007 获取分享码 本书目 ...

  6. 037_go语言中的互斥锁

    代码演示: package main import ( "fmt" "math/rand" "runtime" "sync&quo ...

  7. JS 获取验证码按钮改变案例

    HTML代码 <div class="box"> <label for="">手机号</label> <input t ...

  8. 教你几招,快速创建 MySQL 五百万级数据,愉快的学习各种优化技巧

    我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...

  9. ACL权限管理 学习

    #查看权限 getfacl 文件名 例子:getfacl test 结果:# file: test# owner: root# group: rootuser::rw-group::r-xother: ...

  10. C#LeetCode刷题之#852-山脉数组的峰顶索引(Peak Index in a Mountain Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4003 访问. 我们把符合下列属性的数组 A 称作山脉: A.le ...