mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
70 lines
4 KiB
Text
70 lines
4 KiB
Text
Usually when extracting information from tt(istream) objects oprshift(), the
|
|
standard extraction operator is perfectly suited for the task as in most
|
|
cases the extracted fields are white-space (or otherwise clearly) separated
|
|
from each other. But this does not hold true in all situations. For example,
|
|
when a web-form is posted to some processing script or program, the receiving
|
|
program may receive the form field's values as em(url-encoded)
|
|
characters: letters and digits are sent unaltered, blanks are sent as tt(+)
|
|
characters, and all other characters start with tt(%) followed by the
|
|
character's
|
|
i(ascii-value) represented by its two digit hexadecimal value.
|
|
|
|
When decoding url-encoded information, simple hexadecimal extraction won't
|
|
work, as that extracts as many hexadecimal characters as available,
|
|
instead of just two. Since the letters tt(a-f`) and tt(0-9) are legal
|
|
hexadecimal characters, a text like tt(My name is `Ed'), url-encoded as
|
|
verb(
|
|
My+name+is+%60Ed%27
|
|
)
|
|
results in the extraction of the hexadecimal values tt(60ed) and tt(27),
|
|
instead of tt(60) and tt(27). The name tt(Ed) disappears from view, which is
|
|
clearly not what we want.
|
|
|
|
In this case, having seen the tt(%), we could extract 2 characters, put
|
|
them in an ti(istringstream) object, and extract the hexadecimal value from
|
|
the tt(istringstream) object. A bit cumbersome, but doable. Other approaches
|
|
are possible as well.
|
|
|
|
|
|
The class ti(Fistream) for em(fixed-sized field istream) defines
|
|
an tt(istream) class supporting both fixed-sized field extractions and
|
|
blank-delimited extractions (as well as unformatted tt(read) calls). The
|
|
class may be initialized as a emi(wrapper) around an existing tt(istream), or
|
|
it can be initialized using the name of an existing file. The class is derived
|
|
from tt(istream), allowing all extractions and operations supported by
|
|
tt(istream)s in general. tt(Fistream) defines the following data members:
|
|
itemization(
|
|
itt(d_filebuf): a filebuffer used when tt(Fistream) reads its information
|
|
from a named (existing) file. Since the filebuffer is only needed in
|
|
that case, and since it must be allocated dynamically, it is defined
|
|
as a tt(unique_ptr<filebuf>) object.
|
|
itt(d_streambuf): a pointer to tt(Fistream)'s tt(streambuf). It points
|
|
to tt(d_filebuf) when tt(Fistream) opens a file by name. When an
|
|
existing tt(istream) is used to construct an tt(Fistream), it
|
|
points to the existing tt(istream)'s tt(streambuf).
|
|
itt(d_iss): an tt(istringstream) object used for the fixed field
|
|
extractions.
|
|
itt(d_width): a tt(size_t) indicating the width of the field to
|
|
extract. If 0 no fixed field extractions is used, but
|
|
information is extracted from the tt(istream) base class object
|
|
using standard extractions.
|
|
)
|
|
Here is the initial section of tt(Fistream)'s class interface:
|
|
verbinclude(//INITIAL examples/fistream/fistream.h)
|
|
As stated, tt(Fistream) objects can be constructed from either a
|
|
filename or an existing tt(istream) object. The class interface therefore
|
|
declares two constructors:
|
|
verbinclude(//CONS examples/fistream/fistream.h)
|
|
When an tt(Fistream) object is constructed using an existing tt(istream)
|
|
object, the tt(Fistream)'s tt(istream) part simply uses the tt(stream)'s
|
|
tt(streambuf) object:
|
|
verbinclude(//CONS1 examples/fistream/fistream.cc)
|
|
When an tt(fstream) object is constructed using a filename, the
|
|
tt(istream) base initializer is given a new tt(filebuf) object to be used as
|
|
its tt(streambuf). Since the class's data members are not initialized before
|
|
the class's base class has been constructed, tt(d_filebuf) can only be
|
|
initialized thereafter. By then, the tt(filebuf) is only available as
|
|
tt(rdbuf), returning a tt(streambuf). However, as it is actually a
|
|
tt(filebuf), a tt(static_cast) is used to cast the tt(streambuf) pointer
|
|
returned by tt(rdbuf) to tt(a filebuf *), so tt(d_filebuf) can be initialized:
|
|
verbinclude(//CONS2 examples/fistream/fistream.cc)
|