Quick Links: |
Provide a stream buffer initialized with a file descriptor. More...
Namespaces | |
namespace | bdls |
bdls::FdStreamBuf | stream buffer constructed with file descriptor |
bdls::FdStreamBuf
, derived from the C++ standard library's bsl::streambuf
that can be associated with a file descriptor. Except for the pubimbue
function, all of the actions that can be performed on an bsl::streambuf
can be performed on a bdls::FdStreamBuf
. An bsl::streambuf
provides public methods for reading from and writing to a stream of data, which are implemented in terms of protected virtual functions. A bdls::FdStreamBuf
provides an implementation of these protected virtual members such that they operate on a given file descriptor. The file descriptor can represent a file, a pipe, or other device, and it can be associated with the bdls::FdStreamBuf
at construction, or by calling the reset
method. Note that a bsl::stream
can be initialized with a bdls::FdStreamBuf
, making it possible to associate the stream with a file descriptor. pubimbue
function may be called, but not with any value other than bsl::locale()
. Furthermore, when called with this value, it has no effect. bdls::FilesystemUtil::FileDescriptor
used in this component is, on Unix, an int
type returned by open
, and on Windows, a HANDLE
type returned by CreateFile
. Ideally, a user would open the file and obtain the platform-independent bdls::FilesystemUtil::FileDescriptor
by calling bdls::FilesystemUtil::open
, which will call the appropriate routine for the platform and return a bdls::FilesystemUtil::FileDescriptor
. A value of bdls::FilesystemUtil::k_INVALID_FD
is used to represent an invalid file handle on both platforms. 0x1a
(ctrl-Z) is recognized as an end of file marker. If it is encountered, it is not returned in the buffer and subsequent reads will indicate that no more input is available. The behavior is undefined if it is not the last byte in the file. Other types of files are not required to end with 0x1a
. For files on Unix and files opened in binary mode on Windows, 0x1a
is treated like any other byte. bsl::streambuf
class used in the usage example are not described here. See documentation in "The C++ Programming Language, Third Edition", by Bjarne Stroustrup, Section 21.6.4, and on the web at: http://www.cplusplus.com/reference/iostream/streambuf
bdls::FdStreamBuf
and bdls::FdStreamBuf_FileHandler
classes here are based on STLPort's implementation of filebuf
and _Filebuf_Base
respectively, with copyright notice as follows: ---------------------------------------------------------------------------- Copyright (c) 1999 Silicon Graphics Computer Systems, Inc. Copyright (c) 1999 Boris Fomitchev This material is provided "as is", with absolutely no warranty expressed or implied. Any use is at your own risk. Permission to use or copy this software for any purpose is hereby granted without fee, provided the above notices are retained on all copies. Permission to modify the code and to distribute modified code is granted, provided the above notices are retained, and a notice that the code was modified is included with the above copyright notice. ----------------------------------------------------------------------------
bdls::FdStreamBuf
will be used for either input or output, but not both. char fileNameBuffer[100]; bsl::sprintf(fileNameBuffer, #ifdef BSLS_PLATFORM_OS_UNIX "/tmp/bdls_FdStreamBuf.usage.1.%d.txt", #else // windows "C:\\TEMP\\bdls_FdStreamBuf.usage.1.%d.txt"; #endif bdls::ProcessUtil::getProcessId()); bdls::FilesystemUtil::remove(fileNameBuffer); assert(0 == bdls::FilesystemUtil::exists(fileNameBuffer));
typedef bdls::FilesystemUtil::FileDescriptor FdType; FdType fd = bdls::FilesystemUtil::open(fileNameBuffer, bdls::FilesystemUtil::e_CREATE, bdls::FilesystemUtil::e_READ_WRITE); assert(bdls::FilesystemUtil::k_INVALID_FD != fd);
bdls::FdStreamBuf
associated with file descriptor fd
; the false
argument indicates that streamBuffer
will not assume ownership of fd
, meaning that when streamBuffer
is destroyed fd
will remain open: { bdls::FdStreamBuf streamBuffer(fd, true, // writable false); // 'fd' won't be closed // when 'streamBuffer' is // destroyed bsl::ostream os(&streamBuffer); os << "Five times nine point five = " << 5 * 9.5 << bsl::endl; }
{ // read it in binary mode bdls::FdStreamBuf streamBuffer(fd, false, // not writable false, // 'streamBuffer' does not // own 'fd' true); // binary mode streamBuffer.pubseekpos(0); char buf[100]; bsl::memset(buf, 0, sizeof(buf)); bsl::istream is(&streamBuffer); char *pc = buf; do { is >> bsl::noskipws >> *pc++; } while ('\n' != pc[-1]); #ifdef BSLS_PLATFORM_OS_UNIX assert(!bsl::strcmp("Five times nine point five = 47.5\n", buf)); #else //On Windows we see a CRLF ('\r\n') instead of a simple LF '\n' assert(!bsl::strcmp("Five times nine point five = 47.5\r\n", buf)); #endif }
\r\n
is translated back to \n
{ // read it back in text mode bdls::FdStreamBuf streamBuffer(fd, false); // not writable // 'fd' will be closed when // streamBuffer is destroyed. // Mode will be binary on // Unix, text on Dos. streamBuffer.pubseekpos(0); char buf[100]; bsl::memset(buf, 0, sizeof(buf)); bsl::istream is(&streamBuffer); char *pc = buf; do { is >> bsl::noskipws >> *pc++; } while ('\n' != pc[-1]); assert(!bsl::strcmp("Five times nine point five = 47.5\n", buf)); }
bdls::FilesystemUtil::remove(fileNameBuffer);
bdls::FdStreamBuf
associated with a temporary file, and then use the public methods of the base class interface, including sputn
, sgetn
and pubseekpos
, to do some I/O and seeking on it. const char line1[] = "To be or not to be, that is the question.\n"; const char line2[] = "There are more things in heaven and earth,\n" "Horatio, than are dreamt of in your philosophy.\n"; const char line3[] = "Wherever you go, there you are. B Banzai\n"; const int lengthLine1 = sizeof(line1) - 1; const int lengthLine2 = sizeof(line2) - 1; const int lengthLine3 = sizeof(line3) - 1;
char fileNameBuffer[100]; bsl::sprintf(fileNameBuffer, #ifdef BSLS_PLATFORM_OS_UNIX "/tmp/bdls_FdStreamBuf.usage.2.%d.txt", #else // windows "C:\\TEMP\\bdls_FdStreamBuf.usage.2.%d.txt", #endif bdls::ProcessUtil::getProcessId());
bdls::FilesystemUtil::remove(fileNameBuffer); assert(false == bdls::FilesystemUtil::exists(fileNameBuffer));
typedef bdls::FilesystemUtil::FileDescriptor FdType; FdType fd = bdls::FilesystemUtil::open(fileNameBuffer, bdls::FilesystemUtil::e_CREATE, bdls::FilesystemUtil::e_READ_WRITE); assert(bdls::FilesystemUtil::k_INVALID_FD != fd);
bdls::FdStreamBuf
object named streamBuffer
associated with the file descriptor fd
. Note that streamBuffer
defaults to assuming ownership of fd
, meaning that when streamBuffer
is cleared, reset, or destroyed, fd
will be closed. Note that FdStreamBuf
implements streambuf
, which provides the public methods used in this example: bdls::FdStreamBuf streamBuffer(fd, true); assert(streamBuffer.fileDescriptor() == fd); assert(streamBuffer.isOpened());
sputn
method to write two lines to the file: streamBuffer.sputn(line1, lengthLine1); streamBuffer.sputn(line2, lengthLine2);
bsl::streamoff status = streamBuffer.pubseekpos(0); assert(0 == status);
lengthLine1
characters of the file into buf
, with the method sgetn
. char buf[1000]; bsl::memset(buf, 0, sizeof(buf)); status = streamBuffer.sgetn(buf, lengthLine1); assert(lengthLine1 == status); assert(!bsl::strcmp(line1, buf));
2 * lengthLine2
characters when only lengthLine2
characters are available in the file to read, so the sgetn
method will stop after reading lengthLine2
characters. The sgetn
method will return the number of chars successfully read: bsl::memset(buf, 0, sizeof(buf));
status = streamBuffer.sgetn(buf, 2 * lengthLine2);
assert(lengthLine2 == status);
assert(!bsl::strcmp(line2, buf));
pubseekpos
method always seeks relative to the beginning. We seek back to the start of the file: status = streamBuffer.pubseekpos(0); assert(0 == status);
assert(lengthLine1 == lengthLine3);
line1
in the file with line3
: status = streamBuffer.sputn(line3, lengthLine3); assert(lengthLine3 == status);
status = streamBuffer.pubseekpos(0);
assert(0 == status);
line3
: bsl::memset(buf, 0, sizeof(buf));
status = streamBuffer.sgetn(buf, lengthLine3);
assert(lengthLine3 == status);
assert(!bsl::strcmp(line3, buf));
line2
: bsl::memset(buf, 0, sizeof(buf));
status = streamBuffer.sgetn(buf, lengthLine2);
assert(lengthLine2 == status);
assert(!bsl::strcmp(line2, buf));
fd
and disconnect streamBuffer
from fd
: status = streamBuffer.clear(); assert(0 == status);
streamBuffer
is now no longer open, and is not associated with a file descriptor: assert(!streamBuffer.isOpened()); assert(bdls::FilesystemUtil::k_INVALID_FD == streamBuffer.fileDescriptor());
bdls::FilesystemUtil::remove(fileNameBuffer);