óÀ½, ÀÌÀü, ´ÙÀ½, ¸¶Áö¸·, Â÷·Ê.
streambuf
Layerstreambuf
°èÃþ »ç¿ëÇϱâ
The istream
and ostream
classes are meant to handle
conversion between objects in your program and their textual representation.
istream
°ú ostream
Ŭ·¡½º´Â ÇÁ·Î±×·¥ÀÇ °´Ã¼µé°ú
±×°ÍµéÀÇ ¹®ÀÚ ±×´ë·ÎÀÇ Ç¥Çö »çÀÌÀÇ ÀüȯÀ» ´Ù·é´Ù.
By contrast, the underlying streambuf
class is for transferring
raw bytes between your program, and input sources or output sinks.
Different streambuf
subclasses connect to different kinds of
sources and sinks.
´ëÁ¶ÀûÀ¸·Î ±âÃʸ¦ ÀÌ·ç´Â streambuf
Ŭ·¡½º´Â ÇÁ·Î±×·¥°ú
ÀÔ·Â ¼Ò½º ¶Ç´Â Ãâ·Â ½ÌÅ©(sink) °£¿¡ ¿ø½Ã(raw) ¹ÙÀÌÆ®¸¦
À̵¿½ÃŲ´Ù. ´Ù¸¥ streambuf
¼ºê Ŭ·¡½ºµé°ú ´Ù¸¥ Á¾·ùÀÇ ¼Ò½º, ½ÌÅ©¸¦ ¿¬°áÇÑ´Ù.
The GNU implementation of streambuf
is still evolving; we
describe only some of the highlights.
streambuf
¿¡ ´ëÇÑ GNU ±¸ÇöÀº ¾ÆÁ÷ Àü°³ ÁßÀÌ´Ù. ¸î¸î
Áß¿äÇÑ ºÎºÐ¸¸ ¼³¸íÇÑ´Ù.
streambuf
streambuf
ÀÇ ¿µ¿ª
Streambuf buffer management is fairly sophisticated (this is a nice way to say "complicated"). The standard protocol has the following "areas":
Streambuf ¹öÆÛ °ü¸®´Â ¸Å¿ì Á¤±³ÇÏ´Ù("º¹ÀâÇÑ"À̶ó´Â Ç¥ÇöÀÌ ³ªÀ» °ÍÀÌ´Ù). Ç¥ÁØ ÇÁ·ÎÅäÄÝ¿¡´Â ´ÙÀ½°ú °°Àº "¿µ¿ª(area)"ÀÌ ÀÖ´Ù.
The GNU streambuf
design extends this, but the details are
still evolving.
GNU streambuff
µðÀÚÀÎÀº ÀÌ°ÍÀ» È®ÀåÇÑ´Ù. ±×·¯³ª ¼¼ºÎ »çÇ×Àº
¾ÆÁ÷ Àü°³ ÁßÀÌ´Ù.
The following methods are used to manipulate these areas.
These are all protected methods, which are intended to be
used by virtual function in classes derived from streambuf
.
They are also all ANSI/ISO-standard, and the ugly names
are traditional.
(Note that if a pointer points to the 'end' of an area,
it means that it points to the character after the area.)
´ÙÀ½ ¸Þ¼Òµå¸¦ »ç¿ëÇØ ÀÌ ¿µ¿ªµéÀ» Á¶ÀÛÇÑ´Ù. À̰͵éÀº protected ¸Þ¼ÒµåÀÌ°í,
streambuf
¿¡¼ ÆÄ»ýµÈ Ŭ·¡½ºµé¿¡ ¼ÓÇÑ °¡»óÇÔ¼ö¿¡
ÀÇÇØ »ç¿ëµÈ´Ù. ±×°ÍµéÀº ¶ÇÇÑ ANSI/ISO Ç¥ÁØÀÌ°í ÀüÅëÀûÀ¸·Î ÃßÇÑ
À̸§ÀÌ´Ù(Æ÷ÀÎÅÍ°¡ ¿µ¿ªÀÇ '³¡'À»
°¡¸®Å°¸é ±×°ÍÀº ¿µ¿ª ´ÙÀ½¿¡ ÀÖ´Â ¹®ÀÚ¸¦ °¡¸®Å²´Ù).
pptr() < epptr ()
, the pptr()
returns a pointer to the current put position.
(In that case, the next write will
overwrite *pptr()
, and increment pptr()
.)
Otherwise, there is no put position available
(and the next character written will cause streambuf::overflow
to be called).
pptr() < epptr()
À̸é, pptr()Àº ÇöÀç put À§Ä¡(position)¸¦ °¡¸®Å°´Â
Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù(ÀÌ °æ¿ì, ´ÙÀ½ ¾²±â´Â *pptr()
¸¦ µ¤¾î¾µ °ÍÀÌ´Ù.
±×¸®°í pptr()
À» Áõ°¡½ÃŲ´Ù). ±×·¸Áö ¾ÊÀ¸¸é, »ç¿ëÇÒ ¼ö
ÀÖ´Â put À§Ä¡°¡ ¾ø´Ù(±×¸®°í
¾²¿©Áø ´ÙÀ½ ¹®ÀÚ°¡ streambuf::overflow
¸¦ È£ÃâÇÒ °ÍÀÌ´Ù).
gptr() < egptr ()
, then gptr()
returns a pointer to the current get position.
(In that case the next read will read *gptr()
,
and possibly increment gptr()
.)
Otherwise, there is no read position available
(and the next read will cause streambuf::underflow
to be called).
gptr() < egptr()
À̸é, gptr()
´Â ÇöÀç
get À§Ä¡¸¦ °¡¸®Å°´Â
Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù(ÀÌ °æ¿ì ´ÙÀ½ Àбâ´Â *gptr()
À» ÀÐ°í °¡´ÉÇϸé gptr()
À»
Áõ°¡½Ãų °ÍÀÌ´Ù). ±×·¸Áö ¾ÊÀ¸¸é, ÀÌ¿ëÇÒ ¼ö ÀÖ´Â Àбâ À§Ä¡°¡ ¾ø´Ù(±×¸®°í ´ÙÀ½
Àбâ´Â streambuf::underflow
¸¦ È£ÃâÇÒ °ÍÀÌ´Ù).
overflow
overflow
Suppose you have a function write_to_window
that
writes characters to a window
object. If you want to use the
ostream function to write to it, here is one (portable) way to do it.
This depends on the default buffering (if any).
window
°´Ã¼¿¡ ¹®ÀÚ¸¦ ¾²´Â write_to_window
ÇÔ¼ö°¡ ÀÖ´Ù°í °¡Á¤ÇÏÀÚ. ¸¸¾à ostream ÇÔ¼ö¸¦ »ç¿ëÇØ ±×°Í¿¡ ¾²·Á°í Çϸé,
¿©±â¿¡ ¾Ë¸ÂÀº ¹æ¹ýÀÌ ÀÖ´Ù. ÀÌ°ÍÀº ±âº» buffering¿¡ ÀÇÁ¸ÇÑ´Ù.
#include <iostream.h> /* Returns number of characters successfully written to win. */ extern int write_to_window (window* win, char* text, int length); class windowbuf : public streambuf { window* win; public: windowbuf (window* w) { win = w; } int sync (); int overflow (int ch); // Defining xsputn is an optional optimization. // (streamsize was recently added to ANSI C++, not portable yet.) streamsize xsputn (char* text, streamsize n); }; int windowbuf::sync () { streamsize n = pptr () - pbase (); return (n && write_to_window (win, pbase (), n) != n) ? EOF : 0; } int windowbuf::overflow (int ch) { streamsize n = pptr () - pbase (); if (n && sync ()) return EOF; if (ch != EOF) { char cbuf[1]; cbuf[0] = ch; if (write_to_window (win, cbuf, 1) != 1) return EOF; } pbump (-n); // Reset pptr(). return 0; } streamsize windowbuf::xsputn (char* text, streamsize n) { return sync () == EOF ? 0 : write_to_window (win, text, n); } int main (int argc, char**argv) { window *win = ...; windowbuf wbuf(win); ostream wstr(&wbuf); wstr << "Hello world!\n"; }
streambuf
objectsstreambuf
objects
The GNU streambuf
class supports printf
-like
formatting and scanning.
GNU streambuf
Ŭ·¡½º´Â printf
°°Àº Æ÷¸ËÆðú
½ºÄ³´×À» Áö¿øÇÑ´Ù.
fprintf(file, format, ...)
.
The format is a printf
-style format control string, which is used
to format the (variable number of) arguments, printing the result on
the this
streambuf. The result is the number of characters printed.
]
fprintf(file, format, ....)
¿Í
ºñ½ÁÇÑ´Ù. formatÀº printf
½ºÅ¸ÀÏÀÇ Æ÷¸Ë
Á¦¾î ¹®ÀÚ¿ÀÌ´Ù. ÀÌ ¹®ÀÚ¿Àº (¿©·¯ °³ÀÇ) ÀÎÀÚ¸¦ Æ÷¸ËÇÏ°í °á°ú¸¦
this
streambuf¿¡ Ãâ·ÂÇÑ´Ù. °á°ú´Â Ãâ·ÂµÈ ¹®ÀÚÀÇ ¼ö´Ù.
vfprintf(file, format, args)
.
The format is a printf
-style format control string, which is used
to format the argument list args, printing the result on
the this
streambuf. The result is the number of characters printed.
vfprintf(file, format, args)
¿Í ºñ½ÁÇÏ´Ù. formatÀº
printf
½ºÅ¸ÀÏÀÇ Æ÷¸Ë Á¦¾î ¹®ÀÚ¿·Î ¸Å°³º¯¼ö ¸®½ºÆ®
args¸¦ Æ÷¸ËÇÏ°í this
streambuf¿¡ °á°ú¸¦ Ãâ·ÂÇÑ´Ù. °á°ú´Â Ãâ·ÂµÈ ¹®ÀÚµéÀÇ ¼ö´Ù.
fscanf(file, format, ...)
.
The format is a scanf
-style format control string, which is used
to read the (variable number of) arguments from the this
streambuf.
The result is the number of items assigned, or EOF
in case of
input failure before any conversion.
fscanf(fileformat, ...)
°ú
ºñ½ÁÇÏ´Ù. formatÀº scanf
½ºÅ¸ÀÏÀÇ Æ÷¸Ë
Á¦¾î ¹®ÀÚ¿ÀÌ´Ù. ÀÌ ¹®ÀÚ¿Àº (¿©·¯ °³ÀÇ) ÀÎÀÚ¸¦ this
streambuf¿¡¼ ÀоîµéÀδÙ.
°á°ú´Â ´ëÀÔµÈ ¾ÆÀÌÅÛÀÇ °³¼öÀ̰ųª º¯È¯ Àü ÀÔ·Â ½ÇÆÐ °æ¿ì¿¡ ³ª¿À´Â EOF
´Ù.
streambuf::scan
, but takes a single va_list
argument.
streambuf::scan
°ú ºñ½ÁÇÏ´Ù, ±×·¯³ª ´ÜÀÏ va_list
ÀÎÀÚ¸¦
¹Þ´Â´Ù.
stdio
stdio
A stdiobuf is a streambuf
object that points to
a FILE
object (as defined by stdio.h
).
All streambuf
operations on the stdiobuf
are forwarded
to the FILE
. Thus the stdiobuf
object provides a
wrapper around a FILE
, allowing use of streambuf
operations on a FILE
. This can be useful when mixing
C code with C++ code.
stdiobuf´Â FILE
°´Ã¼(stdio.h
¿¡ Á¤ÀǵÈ)¸¦ °¡¸®Å°´Â streambuf
°´Ã¼´Ù. stdiobuf
ÀÇ ¸ðµç streambuf
¿ÀÆÛ·¹À̼ÇÀº FILE
¿¡ Àü´ÞµÈ´Ù. ±×·¯¹Ç·Î
stdiobuf
°´Ã¼´Â FILE
¿¡ ·¡ÆÛ¸¦ Á¦°øÇØ
FILE
¿¡¼ streambuf
¸¦ »ç¿ëÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù.
ÀÌ°ÍÀº C Äڵ带 C++ ÄÚµå¿Í ¼¯À»(mix) ¶§ À¯¿ëÇÏ´Ù.
The pre-defined streams cin
, cout
, and cerr
are
normally implemented as stdiobuf
objects that point to
respectively stdin
, stdout
, and stderr
. This is
convenient, but it does cost some extra overhead.
¹Ì¸® Á¤ÀǵÈ(pre-defined) ½ºÆ®¸² cin
, cout
,
and cerr
Àº ÀϹÝÀûÀ¸·Î °¢°¢ stdin
, stdout
,
stderr
¸¦ °¡¸®Å°´Â stdiobuf
°´Ã¼·Î ±¸ÇöµÈ´Ù. ÀÌ°ÍÀº ¸Å¿ì Æí¸®ÇÏÁö¸¸, ¾à°£ÀÇ
¿À¹öÇìµå°¡ ÀÖ´Ù.
If you set things up to use the implementation of stdio
provided
with this library, then cin
, cout
, and cerr
will be
set up to use stdiobuf
objects, since you get their benefits
for free. See section C Input and Output.
¸¸¾à ÀÌ ¶óÀ̺귯¸®·Î Á¦°øµÈ stdio
¸¦ ±¸ÇöÇϱâ À§ÇØ
¼³Á¤Çϸé, ´ç½ÅÀÇ Á¦¾à¾øÀÌ ±×°ÍµéÀÇ ÀÌÁ¡À» ¾ò±â ¶§¹®¿¡
cin
, cout
, cerr
˼
stdiobuf
°´Ã¼µéÀ»
»ç¿ëÇÏ¿© ¼³Á¤ÇÒ °ÍÀÌ´Ù. C ÀԷ°ú
Ãâ·Â ÀýÀ» Âü°íÇ϶ó.
The procbuf class is a GNU extension. It is derived from
streambuf
. A procbuf
can be closed (in which case
it does nothing), or open (in which case it allows communicating
through a pipe with some other program).
procbuf Ŭ·¡½º´Â GNU È®ÀåÀ¸·Î streambuf
¿¡¼ ÆÄ»ýµÇ¾ú´Ù.
procbuf
´Â (¾Æ¹« °Íµµ ¾ø´Â °æ¿ì) ´ÝÇôÁú
¼ö Àְųª (ÇÑ ÇÁ·Î±×·¥¿¡¼ ´Ù¸¥ ÇÁ·Î±×·¥À¸·Î
ÆÄÀÌÇÁ¸¦ ÅëÇØ Åë½ÅÀ» Çã¶ôÇÒ °æ¿ì) ¿¸°´Ù.
procbuf
in a closed state.
procbuf
¸¦ closed »óÅ·Π¸¸µç´Ù.
½©(`/bin/sh')À» command¿¡ ÀÇÇØ ÁöÁ¤µÈ ÇÁ·Î±×·¥À» ½ÇÇàÇÑ´Ù.
If mode is `ios::in', standard output from the program is sent
to a pipe; you can read from the pipe by reading from the
procbuf
. (This is similar to `popen(command, "r")'.)
¸¸¾à mode°¡ `ios::in'À̸é ÇÁ·Î±×·¥ÀÇ Ç¥ÁØ
Ãâ·ÂÀº ÆÄÀÌÇÁ·Î
º¸³»Áø´Ù. procbuf
¿¡¼ ÀÐÀ½À¸·Î½á ÆÄÀÌÇÁ·ÎºÎÅÍ ÀÐÀ» ¼ö ÀÖ´Ù(ÀÌ°ÍÀº
`popen(command, "r")'¿Í ºñ½ÁÇÏ´Ù).
If mode is `ios::out', output written to the
procbuf
is written to a pipe; the program is set up to read its
standard input from (the other end of) the pipe. (This is similar to
`popen(command, "w")'.)
¸¸¾à mode°¡ `ios::out'À̸é procbuf
¿¡ ¾²¿©Áø Ãâ·ÂÀº
ÆÄÀÌÇÁ¿¡ ¾²¿©Áø´Ù. ÇÁ·Î±×·¥Àº ÆÄÀÌÇÁ(ÀÇ ´Ù¸¥ ÇÑ ÂÊ)¿¡¼ Ç¥ÁØ ÀÔ·ÂÀ» Àбâ À§ÇØ ¼³Á¤µÈ´Ù( ÀÌ°ÍÀº
`popen(command, "w")'¿Í ºñ½ÁÇÏ´Ù).
The procbuf
must start out in the closed state.
Returns `*this' on success, and `NULL' on failure.
procbuf
´Â closed »óÅ·Π½ÃÀ۵Ǿî¾ß¸¸ ÇÑ´Ù. ¼º°øÇϸé `*this'¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé
`NULL'À» ¸®ÅÏÇÑ´Ù.
The GNU iostream library allows you to ask a streambuf
to
remember the current position. This allows you to go back to this
position later, after reading further. You can back up arbitrary
amounts, even on unbuffered files or multiple buffers' worth, as long as
you tell the library in advance. This unbounded backup is very useful
for scanning and parsing applications. This example shows a typical
scenario:
GNU iostream ¶óÀ̺귯¸®´Â streambuf
°¡ ÇöÀç À§Ä¡¸¦
±â¾ïÇÏ°Ô ÇÑ´Ù.
ÀÌ°ÍÀº Á»´õ ÀÐÀº ÈÄ¿¡ ÀÌ À§Ä¡·Î µ¹¾Æ°¡´Â
°ÍÀ» Çã¶ôÇÑ´Ù. ¹Ì¸® ¶óÀ̺귯¸®¿¡ ¾Ë·È´Ù¸é ¹öÆÛ¸®µå ¾È µÈ ÆÄÀÏ ¶Ç´Â ´ÙÁß ¹öÆÛ
°ªÀÌ¶óµµ ¿øÇÏ´Â ¸¸Å ¹é¾÷ÇÒ ¼ö ÀÖ´Ù. ÀÌ Á¦¾à¾ø´Â ¹é¾÷Àº ½ºÄ³´×°ú ÆĽÌ
ÀÀ¿ë ÇÁ·Î±×·¥¿¡ ¸Å¿ì À¯¿ëÇÏ´Ù. ÀÌ ¿¹´Â ÀüÇüÀûÀÎ °³¿ä¸¦ º¸¿©ÁØ´Ù.
// Read either "dog", "hound", or "hounddog". // If "dog" is found, return 1. // If "hound" is found, return 2. // If "hounddog" is found, return 3. // If none of these are found, return -1. int my_scan(streambuf* sb) { streammarker fence(sb); char buffer[20]; // Try reading "hounddog": if (sb->sgetn(buffer, 8) == 8 && strncmp(buffer, "hounddog", 8) == 0) return 3; // No, no "hounddog": Back up to 'fence' sb->seekmark(fence); // // ... and try reading "dog": if (sb->sgetn(buffer, 3) == 3 && strncmp(buffer, "dog", 3) == 0) return 1; // No, no "dog" either: Back up to 'fence' sb->seekmark(fence); // // ... and try reading "hound": if (sb->sgetn(buffer, 5) == 5 && strncmp(buffer, "hound", 5) == 0) return 2; // No, no "hound" either: Back up and signal failure. sb->seekmark(fence); // Backup to 'fence' return -1; }
streammarker
associated with sbuf
that remembers the current position of the get pointer.
streammarker
¸¦
¸¸µç´Ù.
*this
and mark2 (which must point into the same
streambuffer
as this
).
*this
¿Í ÀÏÄ¡ÇÏ´Â get À§Ä¡¿Í
mark2(this
¿Í °°Àº streambuffer
¸¦
°¡¸®ÄÑ¾ß ÇÑ´Ù) »çÀÌÀÇ Â÷À̸¦ ¸®ÅÏÇÑ´Ù.
An indirectbuf is one that forwards all of its I/O requests to another streambuf.
indirectbuf´Â ´Ù¸¥ streambuf¿¡ I/O ¿äû ¸ðµÎ¸¦ Àü´ÞÇÑ´Ù.
An indirectbuf
can be used to implement Common Lisp
synonym-streams and two-way-streams:
indirectbuf
´Â Common Lisp À¯»ç ½ºÆ®¸²°ú µÎ¹æÇâ
½ºÆ®¸²À¸·Î »ç¿ëÇÒ ¼ö ÀÖ´Ù.
class synonymbuf : public indirectbuf { Symbol *sym; synonymbuf(Symbol *s) { sym = s; } virtual streambuf *lookup_stream(int mode) { return coerce_to_streambuf(lookup_value(sym)); } };