muduo源码解析10-logstream类
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类的更多相关文章
- muduo源码解析5-mutex相关类
mutexlock和mutexlockguard class mutexlock:noncopyable { }: class mutexlockguard:noncopyable { }: 作用: ...
- AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍
AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...
- Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了
这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...
- muduo源码解析11-logger类
logger: class logger { }; 在说这个logger类之前,先看1个关键的内部类 Impl private: //logger内部数据实现类Impl,内部含有以下成员变量 //时间 ...
- Netty源码解析 -- 内存对齐类SizeClasses
在学习Netty内存池之前,我们先了解一下Netty的内存对齐类SizeClasses,它为Netty内存池中的内存块提供大小对齐,索引计算等服务方法. 源码分析基于Netty 4.1.52 Nett ...
- AOP源码解析:AspectJExpressionPointcutAdvisor类
先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...
- java源码解析之Object类
一.Object类概述 Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解 Object的方法可以分成两类,一类是被关键字fin ...
- Bulma 源码解析之 .columns 类
{说明} 这一部分的源码内容被我简化了,另外我还额外添加了一个辅助类 is-grow. .columns // 修饰类 &.is-centered justify-content: cente ...
- java源码解析之String类(二)
上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...
随机推荐
- Python元组运算符
Python元组运算符: len(元组名): 返回元组对象的长度 # len(元组名): # 返回元组对象的长度 tuple_1 = (1,4,5,2,3,6) print(len(tuple_1)) ...
- Python os.tcsetpgrp() 方法
概述 os.tcsetpgrp() 方法用于设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg.高佣联盟 www.cgewang.com 语法 tcsetpgrp()方 ...
- PHP registerXPathNamespace() 函数
实例 为下一个 XPath 查询创建命名空间上下文: <?php$xml=<<<XML高佣联盟 www.cgewang.com<book xmlns:chap=" ...
- Java自学-JDBC 数据库连接池
数据库连接池 与线程池类似的,数据库也有一个数据库连接池. 不过他们的实现思路是不一样的. 本章节讲解了自定义数据库连接池类:ConnectionPool,虽然不是很完善和健壮,但是足以帮助大家理解C ...
- CentOS7系统管理与运维实战
CentOS7系统管理与运维实战 下载地址 https://pan.baidu.com/s/1KFHVI-XjGaLMrh39WuhyCw 扫码下面二维码关注公众号回复100007 获取分享码 本书目 ...
- 037_go语言中的互斥锁
代码演示: package main import ( "fmt" "math/rand" "runtime" "sync&quo ...
- JS 获取验证码按钮改变案例
HTML代码 <div class="box"> <label for="">手机号</label> <input t ...
- 教你几招,快速创建 MySQL 五百万级数据,愉快的学习各种优化技巧
我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...
- ACL权限管理 学习
#查看权限 getfacl 文件名 例子:getfacl test 结果:# file: test# owner: root# group: rootuser::rw-group::r-xother: ...
- C#LeetCode刷题之#852-山脉数组的峰顶索引(Peak Index in a Mountain Array)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4003 访问. 我们把符合下列属性的数组 A 称作山脉: A.le ...