C++的流分析basic_filebuf

  • Post author:
  • Post category:其他



文件流要使用的


io


基础类的枚计类型

class


ios_base


{


public


:



enum


__seekdir


{




beg


= 0x01,                   //


开始



cur


= 0x02,           //


当前



end


= 0x04           //


结尾

};



enum


__iostate


{




goodbit


= 0x00,



badbit


= 0x01,



eofbit


= 0x02,



failbit


= 0x04

};



enum


__openmode


{




app


= 0x01,



ate


= 0x02,



binary


= 0x04,



in


= 0x08,



out


= 0x10,



trunc


= 0x20

};
};

_Filebuf_base


文件缓冲基类

class


_Filebuf_base {


protected


:

_Filebuf_base();


//


打开和关闭文件缓冲区



bool


_M_open(


const


char


*,


ios_base


::


openmode


,


long


__protection);



bool


_M_open(


const


char


*,


ios_base


::


openmode


);



bool


_M_open(


int


__id);



bool


_M_close();

protected


:

//


低级


I/O


读写



ptrdiff_t


_M_read(


char


* __buf,


ptrdiff_t


__n);



bool


_M_write(


char


* __buf,


ptrdiff_t


__n);


//


设置文件偏移位置和文件大小



streamoff


_M_seek(


streamoff


__offset,


ios_base


::


seekdir


__dir);



streamoff


_M_file_size


();

protected


:

//


内存映射


I/O



void


* _M_mmap(


streamoff


__offset,


streamoff


__len);



void


_M_unmap(


void


* __mmap_base,


streamoff


__len);

protected


:



// Returns a value n such that, if pos is the file pointer at the



// beginning of the range [first, last), pos + n is the file pointer at



// the end. On many operating systems n == __last – __first.



streamoff


_M_get_offset(


char


* __first,


char


* __last);



// Returns true if we’re in binary mode or if we’re using an OS or file



// system where there is no distinction between text and binary mode.



bool


_M_in_binary_mode()


const


;

protected


:

#ifdef _MSC_VER



int


_M_hFileMappingObject;


//


映射对象句柄

#endif



int


_M_file_id;       //


文件句柄



ios_base


::


openmode


_M_openmode;    //


打开模式



int


_M_page_size; //


页的大小



bool


_M_is_open      : 1;



bool


_M_should_close : 1;



bool


_M_regular_file : 1;

};
文件缓冲区类

template


<


class


_CharT


,


class


_Traits


>

class


basic_filebuf


:


public


basic_streambuf


<


_CharT


,


_Traits


>,



private


_Filebuf_base

{


public


:


// Types.



typedef


_CharT




char_type


;



typedef


typename


_Traits


::


int_type




int_type


;



typedef


typename


_Traits


::


pos_type




pos_type


;



typedef


typename


_Traits


::


off_type




off_type


;



typedef


_Traits




traits_type


;



typedef


typename


_Traits


::


state_type




_State_type


;



typedef


basic_streambuf


<


_CharT


,


_Traits


>


_Base


;

public


:


basic_filebuf


();

~


basic_filebuf


();

public


:

//


关闭和打开文件



bool


is_open


()


const


;



basic_filebuf


*


open


(


const


char


*,


ios_base


::


openmode


);

//


扩展版本


open()



basic_filebuf


*


open


(


const


char


*,


ios_base


::


openmode


,


long


__protection


);



basic_filebuf


*


open


(


int


__id


);



basic_filebuf


*


close


();

protected


:

// basic_streambuf


基类的重载的虚函数



virtual


streamsize


showmanyc


();



virtual


int_type


underflow


();



virtual


int_type


pbackfail


(


int_type


=


_Traits


::


eof


());



virtual


int_type


overflow


(


int_type


=


_Traits


::


eof


());



virtual


basic_streambuf


<


_CharT


,


_Traits


>*


setbuf


(


char_type


*,


streamsize


);



virtual


pos_type


seekoff


(


off_type


,


ios_base


::


seekdir


,



ios_base


::


openmode


=


ios_base


::


in


|


ios_base


::


out


);



virtual


pos_type


seekpos


(


pos_type


,



ios_base


::


openmode


=


ios_base


::


in


|


ios_base


::


out


);



virtual


int


sync


();



virtual


void


imbue


(


const


locale


&);

private


:

//


内部帮助函数

//


模式



void


_M_exit_putback_mode


();



bool


_M_switch_to_input_mode


();



void


_M_exit_input_mode


();



bool


_M_switch_to_output_mode


();



int_type


_M_input_error


();



int_type


_M_underflow_aux


();




friend


class


_Noconv_output<


_Traits


>;



friend


class


_Noconv_input<


_Traits


>;



friend


class


_Underflow<


basic_filebuf


<


_CharT


,


_Traits


> >;



int_type


_M_output_error


();



bool


_M_unshift


();

//


分配缓存区



bool


_M_allocate_buffers


(


_CharT


*


__buf


,


int


__n


);



bool


_M_allocate_buffers


();



void


_M_deallocate_buffers


();

//


定位缓冲区



pos_type


_M_seek_return


(


off_type


,


_State_type


);



bool


_M_seek_init


(


bool


__do_unshift


);


//


设置字符集转换



void


_M_setup_codecvt


(


const


locale


&);

private


:

//


文件缓冲区用户看到的内部字符缓冲区


:



_CharT


*


_M_int_buf


;



_CharT


*


_M_int_buf_EOS


;

//


对应扩展文件字符的扩展缓冲区



char


*


_M_ext_buf


;



char


*


_M_ext_buf_EOS


;

//


对应内部缓冲区的开始状态



_State_type


_M_state


;

private


:

//


只在输入模式使用的数据成员

// [_M_ext_buf, _M_ext_buf_converted]


包含了扩展字符对应内部缓冲区

// [_M_ext_buf_converted, _M_ext_buf_end]


包含已经读入扩展缓冲区当没有转换内部


equence.



char


*


_M_ext_buf_converted


;



char


*


_M_ext_buf_end


;

//


类似


_M_state


对应内部缓冲区结尾状态



_State_type


_M_end_state


;

//


除非使用内存映射文件


,


否则为空指针



void


*


_M_mmap_base


;



streamoff


_M_mmap_len


;

private


:

//


只在输出模式使用的数据成员



_CharT


*


_M_saved_eback


;



_CharT


*


_M_saved_gptr


;



_CharT


*


_M_saved_egptr


;



enum


{


_S_pback_buf_size


= 8 };



_CharT


_M_pback_buf


[


_S_pback_buf_size


];

private


:

//


本地化信息


(


不关心


)



typedef


codecvt


<


_CharT


,


char


,


_State_type


>


_Codecvt


;



const


_Codecvt


*


_M_codecvt


;



int


_M_width


;


//


编码宽度


(if constant), else 1



int


_M_max_width


;


//


单个字符最低宽度



bool


_M_constant_width


: 1;



bool


_M_always_noconv


: 1;

private


:

//


模式标记



bool


_M_int_buf_dynamic


: 1;


// True


内部缓冲区是堆分配



// false


由用户提供



bool


_M_in_input_mode


: 1;



bool


_M_in_output_mode


: 1;



bool


_M_in_error_mode


: 1;



bool


_M_in_putback_mode


: 1;

};

这个成员必须流在执行任何


IO


操作之前调用


,


否则没有作用

// __buf == 0 && __n == 0 means to make ths stream unbuffered.

// __buf != 0 && __n > 0 means to use __buf as the stream’s internal

// buffer, rather than the buffer that would otherwise be allocated

// automatically. __buf must be a pointer to an array of _CharT whose

// size is at least __n.

template


<


class


_CharT


,


class


_Traits


>

basic_streambuf


<


_CharT


,


_Traits


>*

basic_filebuf


<


_CharT


,


_Traits


>::


setbuf


(


_CharT


*


__buf


,


streamsize


__n


)

{




if


(!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&

_M_int_buf == 0) {




if


(


__buf


== 0 &&


__n


== 0)

_M_allocate_buffers(0, 1);



else


if


(


__buf


!= 0 &&


__n


> 0)

_M_allocate_buffers(


__buf


,


__n


);

}



return


this


;

}

seekoff()

// __off


是偏移量


(


整型


),


__whence


是方向


(


枚计类型


)


从开始


,


当前


,


结尾偏移


),


该函数主要还是调用另外一个方法基类的函数


_M_seek


实现


, _M_seek


则调用


lseek


系统函数实现

_M_seek


定义如下:参数(偏移量和方向),放回lseek的返回值

_M_seek(streamoff offset, ios_base::seekdir dir)

template


<


class


_CharT


,


class


_Traits


>

typename


basic_filebuf


<


_CharT


,


_Traits


>::


pos_type

basic_filebuf


<


_CharT


,


_Traits


>::


seekoff


(


off_type


__off


,



ios_base


::


seekdir


__whence,



ios_base


::


openmode


/* dummy */


)

{




if


(


this


->


is_open


() &&

(


__off


== 0 || (_M_constant_width &&


this


->_M_in_binary_mode())))

{


//


定位初始化



if


(!_M_seek_init(


__off


!= 0 || __whence !=


ios_base


::


cur


))



return


pos_type


(-1);

//


从到头或尾定位


,


不管是否输入模式



if


(__whence ==


ios_base


::


beg


|| __whence ==


ios_base


::


end


)

return _M_seek_return(this->_M_seek(_M_width * __off, __whence),

_State_type());

//


从当前位置定位


,


如果在输入模式问题就复杂化

else


if


(__whence ==


ios_base


::


cur


) {




if


(!_M_in_input_mode)

return _M_seek_return(this->_M_seek(_M_width * __off, __whence),

_State_type());


//


使用了内存映射


.



else


if


(_M_mmap_base != 0) {




// __off is relative to gptr(). We need to do a bit of arithmetic



// to get an offset relative to the external file pointer.



streamoff


__adjust =


this


->


gptr


() – (


_CharT


*) _M_mmap_base;




return


_M_seek_return(


this


->_M_seek(


__off


+ __adjust – _M_mmap_len,



ios_base


::


cur


),

_State_type());

}

//


使用固定字符宽度



else


if


(_M_constant_width) {


// Get or set the position.



streamoff


__iadj = _M_width * (


this


->


gptr


() –


this


->


eback


());



// Compensate for offset relative to gptr versus offset relative



// to external pointer. For a text-oriented stream, where the



// compensation is more than just pointer arithmetic, we may get



// but not set the current position.



if


(__iadj <= _M_ext_buf_end – _M_ext_buf) {




streamoff


__eadj =

_M_get_offset(_M_ext_buf, _M_ext_buf + __iadj) –

_M_get_offset(_M_ext_buf, _M_ext_buf_end);



streamoff


__cur =


this


->_M_seek(


__off


,


ios_base


::


cur


);



if


(__cur != -1 && __cur + __eadj >= 0)



return


_M_seek_return(__cur + __eadj, _State_type());



else



return


pos_type


(-1);

}



else



return


pos_type


(-1);

}

//


使用编码宽度



else


{


// Get the position. Encoding is var width.



// Get position in internal buffer.



ptrdiff_t


__ipos =


this


->


gptr


() –


this


->


eback


();




// Get corresponding position in external buffer.

_State_type __state = _M_state;



int


__epos = _M_codecvt->


length


(__state, _M_ext_buf, _M_ext_buf_end,

__ipos);



// Sanity check (expensive): make sure __epos is the right answer.

_State_type __tmp_state = _M_state;

_Filebuf_Tmp_Buf<


_CharT


,


_Traits


> __buf(__ipos);



_CharT


* __ibegin = __buf._M_ptr;



_CharT


* __inext = __ibegin;



const


char


*


__dummy


;



typename


_Codecvt::


result


__status

= _M_codecvt->


in


(__tmp_state,

_M_ext_buf, _M_ext_buf + __epos,


__dummy


,

__ibegin, __ibegin + __ipos, __inext);



if


(__status != _Codecvt::


error


&&

(__status == _Codecvt::


noconv


||

(__inext == __ibegin + __ipos &&



equal


(


this


->


gptr


(),


this


->


eback


(), __ibegin,

_Eq_traits<


traits_type


>())))) {




// Get the current position (at the end of the external buffer),



// then adjust it. Again, it might be a text-oriented stream.



streamoff


__cur =


this


->_M_seek(0,


ios_base


::


cur


);



streamoff


__adj =



this


->_M_get_offset(_M_ext_buf, _M_ext_buf + __epos) –



this


->_M_get_offset(_M_ext_buf, _M_ext_buf_end);



if


(__cur != -1 && __cur + __adj >= 0)



return


_M_seek_return(__cur + __adj, __state);



else



return


pos_type


(-1);

}



else




// We failed the sanity check.



return


pos_type


(-1);

}

}



else




// Unrecognized value for __whence.



return


pos_type


(-1);

}



else



return


pos_type


(-1);

}

seekpos()


该函数桶上述的函数类似


,


还是调用


_M_seek


函数来实现


,


不同的是从开始偏移

{ … _M_seek(


__off


,


ios_base


::


beg


) …}

template


<


class


_CharT


,


class


_Traits


>

typename


basic_filebuf


<


_CharT


,


_Traits


>::


pos_type

basic_filebuf


<


_CharT


,


_Traits


>::


seekpos


(


pos_type


__pos,



ios_base


::


openmode


/* dummy */


)

{




if


(


this


->


is_open


()) {




if


(!_M_seek_init(


true


))



return


pos_type


(-1);



streamoff


__off


=


off_type


(__pos);



if


(


__off


!= -1 &&


this


->_M_seek(


__off


,


ios_base


::


beg


) != -1) {


_M_state = __pos.


state


();



return


_M_seek_return(


__off


, __pos.


state


());

}



else



return


pos_type


(-1);

}



else



return


pos_type


(-1);

}

// Wrapper for lseek or the like.

streamoff


_Filebuf_base::_M_seek(


streamoff


offset


,


ios_base


::


seekdir


dir


)

{




streamoff


result


= -1;



int


whence;



switch


(


dir


) {




case


ios_base


::


beg


:



if


(


offset


< 0 ||


offset


> _M_file_size())



return


-1;

whence =


SEEK_SET


;



break


;



case


ios_base


::


cur


:

whence =


SEEK_CUR


;



break


;



case


ios_base


::


end


:



if


(


offset


> 0 || –


offset


> _M_file_size())



return


-1;

whence =


SEEK_END


;



break


;



default


:



return


streamoff


(-1);

}



result


= LSEEK(_M_file_id,


offset


, whence);



return


result


;

}

// Helper functiosn for seek and imbue

template


<


class


_CharT,


class


_Traits>

typename


basic_filebuf


<_CharT, _Traits>::


pos_type

basic_filebuf


<_CharT, _Traits>::_M_seek_return(


off_type


__off,

_State_type __state) {




if


(__off != -1) {




if


(_M_in_input_mode)

_M_exit_input_mode();

_M_in_output_mode =


false


;

_M_in_putback_mode =


false


;

_M_in_error_mode =


false


;



this


->


setg


(0, 0, 0);



this


->


setp


(0, 0);

}



pos_type


__result(__off);

__result.


state


(__state);



return


__result;

}



版权声明:本文为linweixuan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。