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. 5分钟白嫖我常用的免费效率软件/工具!效率300% up!

    Mac 免费效率软件/工具推荐 1. uTools(Windows/Mac) 还在为了翻译 English 而专门下载一个翻译软件吗? 还在为了格式某个 json 文本.时间戳转换而打开网址百度地址吗 ...

  2. linux下使用vscode和makefile搭建C++开发环境

    最近在linux上跑一些开源库做学习用, 顺手就搭了一下vscode的c++开发环境, 这里分享一下vscode进行C++开发的基本环境结构. 1. 首先是编辑器, vscode直接官网下载的, 后期 ...

  3. Jenkins总结3-shell脚本

    我写shell脚本的功力还很初级,基本都是现学现卖,写得不是很健壮,只能提供个思路,请大家包涵. 我使用的系统只能发函数放到shell最前面.本人还是比较推崇函数式脚本的,方便复用,目前只简单的封装了 ...

  4. SSH整合-hibernate

    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property& ...

  5. FreeSql增加新特性Context

    源 FreeSql 作者做了很完善的组件 我看了一下,感觉很实用,使用上有很大的可自定义操作的地方,跟传统Orm固定格式不同,也异于Dapper的设计,支持表达式树 原地址 https://www.c ...

  6. 家庭记账本APP开发准备(三)

    单选框(RadioButton) 通过设置单选框,可以将非此即彼的问题进行解决,成功学会并应用了手机端单项选择框; 复选框(CheckBox) 学习复选框是为了给使用软件的人更多的选择,在其他选择框后 ...

  7. RabbitMq之消息确认

    最近阅读了rabbitmq的官方文档,然后结合之前面试时被问到关于消息队列的问题来探索一下关于消息队列的消息确认机制. 其实消息确认就是消费者确认消息被消费了, 生产者确认消息已经发送到了消息队列中了 ...

  8. 眼见为实 — CSS的overflow属性

    1. overflow属性 CSS的overflow属性指定当内容溢出一个元素的框,会发生什么.举个栗子: <!DOCTYPE html> <html> <head> ...

  9. Django中的ORM如何通过数据库中的表格信息自动化生成Model 模型类?

    Inspectdb Django项目通过绑定的数据库中的相应表格直接自动化生成Model 模型类 python manage.py inspectdb Django 中的 ORM 可以实现对象关系映射 ...

  10. Java中的引用与ThreadLocal

    Java中的引用--强软弱虚 强引用 Object object = new Object(),这个object就是一个强引用.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回 ...