#include <iostream.h> typedef long streampos; typedef long streamoff;
class ios : virtual public unsafe_ios, public stream_MT { public: enum open_mode { in = 0x01, // open for reading out = 0x02, // open for writing ate = 0x04, // seek to eof upon original open app = 0x08, // append mode: all additions at eof trunc = 0x10, // truncate file if already exists nocreate = 0x20, // open fails if file doesn't exist noreplace= 0x40 // open fails if file already exists };
// stream seek direction enum seek_dir { beg=0, cur=1, end=2 };
// see ios(3CC4) for remainder ... } ;
class streambuf : public stream_MT { public :
int in_avail(); int out_waiting(); int sbumpc(); streambuf* setbuf(char* ptr, int len); streampos seekpos(streampos, int =ios::in|ios::out); streampos seekoff(streamoff, seek_dir, int =ios::in|ios::out); int sgetc(); int sgetn(char* ptr, int n); int snextc(); int sputbackc(char); int sputc(int c); int sputn(const char* s, int n); void stossc(); virtual int sync();
int in_avail_unlocked(); int out_waiting_unlocked(); int sbumpc_unlocked(); int sgetc_unlocked(); int sgetn_unlocked(char* ptr, int n); int snextc_unlocked(); int sputbackc_unlocked(char); int sputc_unlocked(int c); int sputn_unlocked(const char* s, int n); void stossc_unlocked(); };
streambuf 类定义了从中派生实际缓冲区类的基本缓冲区类功能。此公共接口提供了任何流类在执行其与缓冲区相关的函数时可能需要调用的函数。不会创建此类型的对象。相反,缓冲区对象必须属于从 streambuf 派生的某个类类型。有关此类派生所需的受保护接口的论述,请参见 sbufprot (3CC4) 。
为使 streambuf 实现多线程安全,也就是说,能够在多线程环境中正确工作,在每个公共成员函数中都使用了锁。引入了一组无锁的备选公共成员函数以在对性能要求极高的单线程应用程序中使用。这些成员函数与原始函数共享相同的名称,但是附加了后缀 _unlocked。除了是多线程安全的之外,这些成员函数具有完全相同的功能。
类 streambuf 支持抽象缓冲区类。它在逻辑上包括一个字符序列和一个或两个定义了将要存储和/或获取的下一个字符的位置的指针。仅用于输入(或输出)的缓冲区类将仅具有 get(或 put)指针。同时用于输入和输出的缓冲区类将具有两个指针。
应当将 get 和 put 指针理解为序列中的字符之间的指向。要从输入缓冲区中获取的下一个字符是紧跟在 get 指针后的那一个。放置到输出流中的下一个字符将恰好存储在 put 指针之后。当位于序列开头时,指针恰好指向第一个字符之前;位于序列末尾时,它恰好指向最后一个字符之后。
归因于不同的底层设备,可以有各种具有不同策略的缓冲区(也称为保留区)。队列式缓冲区,例如 strstreambuf(请参见 ssbuf(3cc4)),具有独立的 get 和 put 指针。strstreambuf 是一个内存中字符数组并且支持在任意位置进行存储和获取。文件式缓冲区,例如 filebuf(请参见 filebuf(3cc4)),可以同时允许提取和放置操作,但起作用的只有一个指针;下一次提取或放置将始终在当前位置执行。(实际上可以有两个指针,但是它们始终指向相同的位置。)
streambuf 使用字符数组作为缓冲区,并且调用虚拟函数来填充空的输入缓冲区或刷新整个输出缓冲区。(有关详细信息,请参见 sbufprot(3cc4)。)为实现最大效率,存储、获取和指针操纵函数通常是内联的。下文中将对它们进行描述。
此函数返回 get 指针后的字符,如果 get 指针位于序列末尾,则返回 EOF。尽管其名称如此,但此函数不移动 get 指针。
此函数将 get 指针向前移动一个位置,然后返回位于 get 指针的新位置后的字符。如果在调用此函数之前或之后 get 指针位于序列末尾(没有字符可用),则此函数返回 EOF。示例:假定输入缓冲区如下所示:
abc|def
其中,'|' 表示 get 指针的位置。此函数将向前移动 get 指针并返回 'e'。
此函数可能应当称为 "sgetc"。它将 get 指针向前移动一个位置并返回它经过的字符。如果 get 指针当前位于序列末尾,则此函数返回 EOF。
此函数将 get 指针向前移动一个位置;它不返回任何东西。不使用放回,可以使用 sgetc 和 stossc 的组合实现扫描程序,因为 sgetc 提供了向前查找。
此函数获取跟在 get 指针后的接下来的 len 个字符,将它们复制到 ptr 指向的 char 数组中;它将 get 指针向前移动到所获取的最后一个字符之后。如果剩余的字符少于 len 个,则有多少字符可用它就获取多少。它返回所获取的字符数。
此函数尝试将 get 指针向后移动一个字符并将 c 放置在新位置。取决于底层的缓冲机制,有可能无法将指针向后移动,也有可能无法将 c 存储在该位置。因此,如果 c 不是与恰好位于 get 指针前的字符相同,则此函数的影响是不确定的。同样,取决于底层的缓冲机制,此函数可能需要与外部设备重新同步。如果尝试的放回失败,则此函数返回 EOF。什么算是失败取决于实际缓冲区类的细节,但是可能包括已位于设备的开头。
此函数返回获取区中立即可用的字符数。确定可以不出错误地获取 i 个字符并且不需要访问任何外部设备。
此函数存储恰好位于 put 指针后的 c,并且将指针向前移动一个位置,可能会扩展序列。它返回 c,在发生错误时返回 EOF。什么算是错误取决于实际的派生缓冲区类。
从 ptr 指向的位置开始,存储 put 指针后的恰好 len 个字符,并且将 put 指针向前移动到最后一个字符之后。它返回所存储的字符数,这应该是 len。所存储的字符数少于 len 表明发生了某种错误。
此函数返回放置区中的字符数,即等待输出到最终目的地的字符数。
此函数重新放置 get 和/或 put 指针,具体取决于 mode 中设置的位。如果 mode 中设置了 ios::in,则将移动 get 指针;如果 mode 中设置了 ios::out,则将移动 put 指针。要移动的距离为 off(一个有符号数量)。dir 的可能值为
从流的开头移动 off 个字节。
从当前位置移动 off 个字节。
从流的末尾移动 off 个字节。
此函数返回新位置,如果无法根据请求调整流的位置,则返回 EOF。注意:并非所有流都支持位置调整。注意:返回的位置(类型为 streampos)不应当是任何算术运算的主体,但应当被视为“幻数”值。
此函数将 get 和/或 put 指针(具体取决于 mode 中设置的位)重新放置到位置 pos。如果 mode 中设置了 ios::in,则将移动 get 指针;如果 mode 中设置了 ios::out,则将移动 put 指针。pos 的值应当是之前的 seekoff 或 seekpos 调用返回的值,但是有两个具有约定意义的特殊值:
(streampos)0 - the beginning of the stream; (streampos)EOF - error indicator.
此函数将 streambuf 与其实际字符流进行同步。细节取决于特定的派生缓冲区类。通常,如果可能,放置区中的任何字符都将刷新到其最终目的地,输入缓冲区中的任何字符都将返回到其来源。这通常意味着 in_avail() 和 out_waiting() 在 sync 后都将返回零。此函数在发生任何错误时返回 EOF,在成功时返回零。
此函数从逻辑上来讲应当放在受保护的接口中,但是为了与原始流软件包兼容,它被放置到了公共接口中。此函数尝试使用开头位于 ptr 指向的位置的 len 字节的数组作为缓冲区。将 ptr 设置为零或者将 len 设置为小于或等于零将请求无缓冲状态。取决于派生类的细节,有可能无法接受该请求。此函数在成功时返回指向 streambuf 的指针,如果无法接受请求则返回零。
ios (3CC4) 、 ios.intro (3CC4) 、 sbufprot (3CC4)
《C++ Library Reference》中的第 3 章 "The Classic iostream Library" 和第 4 章 "Using Classic iostreams in a Multithreaded Environment"。