|
Boost : |
From: Rob Stewart (stewart_at_[hidden])
Date: 2004-09-13 08:43:24
From: "Jeff Garland" <jeff_at_[hidden]>
>
> We are extending the IOStreams review for one week until 9/11/04. While we
> have had many good reviews, the library is quite large and we would like to
> see addtional discussion and review.
I apologize for not getting my review in by 9/11, but I simply
couldn't finish it by then. Even now, I cut things short.
Nevertheless, here is my review.
There are many comments below, but I'll provide the executive
summary first.
_________________________________________________________________
Should the library be accepted into Boost?
Absent Daryle Walker's strong comments against this library, I'd
have said, "Absolutely." Given those comments, I must be more
guarded.
The MoreIO library did less to simplify creating and managing
streams and the cognitive complexity thereof, and it does not
provide the filtering that the Iostreams library offers. Still,
MoreIO offers some facilities and an approach that leads to
questions regarding whether these two are competing or
complementary libraries. While more investigation regarding the
strengths and synergies of the two libraries seems warranted, it
may be best to accept both and sort out the matter later.
_______________________________
Design Evaluation
The library is well conceived and executed. The design seems
sound. There are still questions regarding the overlap and
differences between this library and MoreIO. There are
fundamental, philosophical differences between the libraries.
Use cases should be conceived and compared to see how the
libraries can handle each. Only then will we know whether they
are complementary or competing and, if the latter is the case,
which proves superior according to various criteria including
ease of use and performance. It may well be that the stream[buf]
parts of MoreIO should simply be added to, even integrated with,
this library.
_______________________________
Implementation Evaluation
I did not have the time to study the implementation.
_______________________________
Documentation Evaluation
The documentation is astoundingly thorough and quite clear
overall. Many have already made suggestions for improvement, but
those can only be seen as making good better. I have included
lengthy comments on the documentation, but I could not even visit
every page!
_______________________________
Potential Usefulness Evaluation
This library makes creating streams and streambufs accessible to
many more programmers than does the Standard IOStreams Library.
This means that programmers will be able to create useful
components they otherwise might avoid creating. This means the
library should prove extremely useful.
_______________________________
Miscellaneous
I did not have the time to use the library. My review was based
soley upon the documentation and some inspection of the code.
I spent many hours reading the documentation (much to my wife's
chagrin!).
I have written manipulators and a few streambufs over the years,
but I'm not truly expert with the inner world of streams and
streambufs.
_________________________________________________________________
Library Name
I agree with the sentiment of other reviewers in that the library
is misnamed. Since this library provides filtering, complete
with chaining, as well as to make it easy to create streambufs
and streams, the current name fails to capture all of these
features. Since the Standard Library provides streambufs,
streams, manipulators, etc., and yet it is called the IOStreams
Library, perhaps there's nothing wrong with simply calling this
library Boost.IOStreams. (I do think this library should use the
same capitalization: "IOStreams" not "Iostreams.")
_________________________________________________________________
Design Comments
_______________________________
Miscellaneous
Wouldn't the InoutResource concept be better named
"BidirectionalResource," though that is longer? (Same for
InoutFilter.)
"Peekable" does not imply being able to put back a character.
Wouldn't "Undoable" be a better name for this optional behavior?
The normal template parameter abbreviation for a character type
is "Char." I don't think abbreviating it to "Ch" is helpful.
There's no information provided on the performance of this
library. How much overhead does it add compared to custom
solutions? For example, how much memory and runtime overhead is
there wrt MoreIO's mechanisms? How much overhead is there wrt a
custom filtering solution? These are answers users of the
library need to judge whether it is sufficient or must they
choose another approach.
The filter chain ordering for input versus output is awkward. It
should always be from the beginning to end; let the library
reverse the order.
_______________________________
boost::io::converter
"converter" isn't well-named. It only widens characters for the
resources it converts, so it should be called something else. So
that begs the new name. I thought of "widener," but while it's
correct English, it's also odd sounding, at least to my ear.
"character_widener," would be a little more explicit. Perhaps
"expander" or "character_expander" would work.
Can converter be used with a wide character resource? Imagine a
generic "widen" which ensures that the resulting streambuf or
stream uses wide characters.
convert's "Int" template parameter is poorly named. "Int" is, of
course, a common abbreviation for "integer" in C++. I suggest
using "Intern" or even "Internal." The name of "IntTr" should
follow suit.
_______________________________
basic_newline_filter
I realize that this is only an example, but there is no apparent
protection from misconfiguring the constructor flags. Grouping
the related options into enumerated types and taking separate
parameters for each group would make it safer to use. (You can
overload the bitwise OR operator to permit combining them
conveniently.) That is, since print_CR, print_LF, and print_CRLF
are mutually exclusive, they should be part of an enumerated type
that does not permit bitwise OR'ing. Since the posix, mac, and
windows values are meant to supplant all of the other values,
they should be part of their own enumerated type and should be
used in a separate constructor. The remaining options can be
part of a third enumerated type, with bitwise OR support, that
constitutes the second argument to the existing constructor.
The ignore_CR and ignore_LF values are poorly named. I suggest
ignore_extra_CRs and ignore_extra_LFs. The print_CR, print_CRLF,
and print_LF values would be better if named write_CR,
write_CRLF, and write_LF, since no printing is occuring, at least
in general.
_________________________________________________________________
boost::io::reverse
Isn't the direction of a filter independent of the filtering?
That is, why isn't a filter's interface based upon these
semantics:
char_type filter(char_type ch);
streamsize filter(char const * input, streamsize n,
char const * output);
Then, the source and destination of the data is under the control
of the filter() function and means that whether the filtering is
used on input or output is an orthogonal decision. This
interface should be every bit as efficient as what you've
specified, but makes filters more straightforward and flexible.
_________________________________________________________________
Documentation Comments
In case it makes a difference, I was reading the documentation at
http://home.comcast.net/~jturkanis/iostreams/libs/io/doc/ on 4
SEP 2004 rather than downloaded documentation.
_______________________________
General
"boiler plate" is one word; I'm guessing it will appear in
various places throughout the documentation, so I'm calling it
out at the top.
When formatting source code may I suggest not indenting twice for
braces? Doing so pushes code too far right and reduces
readability due to long lines. (This occurs on tutorial.html and
read.html, for example.)
When referring to concepts, always capitalize them. Thus,
"filter" becomes "Filter" in most uses, for example.
In many places you mention that something works with a Source or
a "standard input stream or a standard stream buffer" or
similar. Wouldn't it be better to clearly define once that
std::basic_istream models Source, std::basic_ostream models Sink,
std::basic_iostream and std::basic_streambuf model both? Then
you need never mention "standard xxx stream or stream buffer"
again. Otherwise, I'd prefer that "standard input stream" be
spelled "std::basic_istream," that "standard stream buffer" be
spelled "std::basic_streambuf," etc.
_________________________________________________________________
menu.html
_______________________________
Contents
This is confusing. Apparently, the leading "+" means a different
page, whereas entries without the "+" are on the current page,
but there is no legend explaining that.
Why do some pages, like tutorial.html have a mini-TOC at the top,
whereas others, like home.html, which may be the only unique one,
get their sections listed in the Contents frame? I'd prefer to
see all of the pages handled the same. Put another way, remove
"Conventions" and "Acknowledgments" from Contents; they can be
found by looking at home.html.
_________________________________________________________________
home.html
_______________________________
Overview
"In addition to providing an abstract framework the library
...in their own right. These include components...bzip2
formats."
This is difficult to read due to lack of punctuation and other
problems. I suggest rephrasing as:
In addition to providing an abstract framework, the library
provides a number of filters, sources, and sinks, which also
serve as examples of how to use the library. These classes
provide access to memory mapped files, file descriptor-based
file access, code conversion, text filtering using regular
expressions, line-ending conversions, and (de)compression for
the zlib, gzip, bzip2 formats.
Filtering Streams and Stream Buffers
"For filtering data the Iostreams Library provides the templates
^
add comma
filtering_streambuf and filtering_stream. Instances of
filtering_streambuf or filtering_stream contains chains of
^^^^^^^^
subject/verb agreement: change to "contain"
_______________________________
Conventions
The second bullet would be easier to follow if you broke each
piece into a separate bullet:
* Specializations of std::basic_istream will be refered to as
standard input streams
* Specializations of std::basic_ostream as standard output
streams
etc.
I don't think you should "omit the qualifier _standard_ for
brevity." Otherwise, your "conventions" aren't.
There's nothing wrong with what you've done, but why not use the
phrase, "standard streambuf" instead of "standard stream buffer?"
It's shorter and in keeping with what anyone with some
familiarity of Standard IOStreams would expect.
_______________________________
Footnotes
I don't see any text that references the footnotes at the bottom
of the page, so their presence is confusing. (Further reading
reveals that these footnotes appear at the bottom of every page,
regardless of whether they are referenced. May I suggest an
endnotes page to which all references point. The notes won't be
at the foot of the pages which reference them, but they won't
appear on pages that don't.
_________________________________________________________________
tutorial.html
_______________________________
Defining Streams and Stream Buffers for a New Data Source
In discussing the hypothetical read() function, you state that,
"If an integer less than n is returned, the end of the stream has
been reached." What about sources for which more characters will
arrive but are not presently available?
" The Iostreams Library allows users to create a standard input
stream or stream buffer by defining a classes with a single
^^^^^^^
class
"Here source is a convenience base class which provides several
member types as well as default implementations of several member
functions. (The member functions are not needed here.)"
The parenthetical sentence is a little confusing. I suggest
rewording like this:
Here, source is a convenience base class which provides
several member types as well as default implementations of
several member functions which aren't used in this example.
"We can also define a standard input stream:"
I suggest italicizing "stream" and rephrasing like the following,
for clarity:
We can also define a standard input <I>stream</I> using
random_source:
" Both streambuf_facade and stream_facade have constructors and
overloads of open which forward their arguments to filter or
^^^^^^^^^
to the filter
resource constructor. Therefore, the first example could have
^^^^^
previous
(That change will avoid making the reader count examples and
wonder which code blocks are examples, and which are not.
Alternatively, should this sort of reference appear elsewhere,
you might consider numbering the examples in a caption so they're
easy to spot and call out by number.)
_______________________________
Defining Streams and Stream Buffers for a New Data Sink
" The case is similar if we wish to define a standard stream
buffer to write to a new type of output device."
That's worded a little awkwardly. I suggest this:
If we wish to define a standard stream buffer to write to a
new type of output device, the required functionality is
similar to that for creating a new data source.
"Here sink is a convenience base class which provides several
member types as well as default implementations of several member
functions. (The member functions are not needed here.)"
The parenthetical sentence is a little confusing. I suggest
rewording like this:
Here, sink is a convenience base class which provides several
member types as well as default implementations of several
member functions which aren't used in this example.
"We can also define a standard output stream:"
I suggest italicizing "stream" and rephrasing like the following,
for clarity:
We can also define a standard output <I>stream</I> using
vector_sink:
_______________________________
Filtering Input
"...from a provided Source and modifies it before returning it to
the user:"
^^^^
caller
" Here input_filter is a convenience base class which provides
several member types as well as default implementations of
several member functions. (The member functions are not needed
here.)"
The parenthetical sentence is a little confusing. I suggest
rewording like this:
Here, input_filter is a convenience base class which provides
several member types as well as default implementations of
several member functions which aren't used in this example.
"The function boost::io::get reads a character from an arbitrary
Source; it is provided by the Iostreams Library to allow all
Sources to be accessed with a single interface."
That's worded awkwardly. I suggest rephrasing like this:
The function boost::io::get reads a character from an
arbitrary Source. This is possible because the Iostreams
Library provides the same interface for all Sources.
"The last item added to the chain could be any Source."
This is the first time you've used the term, "chain," so this is
confusing as written. I suggest the following:
Notice that push is overloaded to accept both filters and
sources (an alphabetic_input_filter and std::cin, in this
case). When you push multiple items (one or more filters and
possibly a source), you form a "chain." A source is only
valid as the last item in a chain.
In the following example, reproduced here, the order seems
backward:
filtering_streambuf<input> in;
in.push(alphabetic_input_filter());
in.push(random_source());
If that's the correct order, then you need to explain, even here
in the tutorial, why the order is as shown.
"We could also add any number of InputFilters to the chain before
adding the Source."
Since "we" aren't doing this, it would read better if written
like this:
Any number of InputFilters can be added to the chain before
adding the Sink.
"They could also use the following convenience typedefs:"
I'm not sure what the antecedent to "they" was supposed to be,
but I suggest rephrasing that like this:
The following typedefs can make using the foregoing types
easier:
_______________________________
Filtering Output
I suggest that your example convert text to lower case as this
will eliminate language concerns about being able to map a single
lower case character to multiple upper case characters.
" Here output_filter is a convenience base class which provides
several member types as well as default implementations of
several member functions. (The member functions are not needed
here.)"
The parenthetical sentence is a little confusing. I suggest
rewording like this:
Here, output_filter is a convenience base class which provides
several member types as well as default implementations of
several member functions which aren't used in this example.
"The function boost::io::put writes a character to an arbitrary
Sink; it is provided by the Iostreams Library to allow all Sinks
to be accessed with a single interface."
That would read better like this:
The function boost::io::put writes a character to an arbitrary
Sink. All Iostreams Library Sinks use the same interface.
"We could also add any number of OutputFilters to the chain
before adding the Sink."
Since "we" aren't doing this, it would read better if written
like this:
Any number of OutputFilters can be added to the chain before
adding the Sink.
"They could also use the following convenience typedefs:"
I'm not sure what the antecedent to "they" was supposed to be,
but I suggest rephrasing that like this:
The following typedefs can make using the foregoing types
easier:
_______________________________
Efficient Filtering: Buffered Filters
"In such cases, each time a character is read from an ordinary
InputFilter one incurs the overhead of a call to its member
function get."
You've changed from "we" to "one" and it sounds odd. Try this:
In such cases, reading a character from an ordinary
InputFilter means calling its get member function, thus
incurring the overhead of a (virtual?) function call.
"To avoid this overhead, the library allows users to define
Buffered filters which can process several characters at once by
implementing a member function read. This function will typically
be called only when the buffer associated with the filter by the
Iostreams Library becomes full."
The reference to "users" instead of "us" sounds odd, and the
second sentence is phrased awkwardly.
To avoid this overhead, we can create a Buffered filtered
which can process several characters at once by implementing a
read member function in lieu of the get member function. The
Iostreams Library typically calls read only when the buffer
associated with the filter is full. That means that the
larger the buffer is, the fewer times read must be called,
reducing its overhead.
(It isn't clear from the tutorial whether read supplants get or
augments it. I assumed the former in writing the above.)
"OutputFilters can also be Buffered. For example:"
You should mention that this is via the write mf:
The Iostreams Library also supports Buffered OutputFilters via
the member function write. Here's the Buffered version of the
toupper_filter:
_________________________________________________________________
examples.html
_______________________________
Tab-expanding OutputFilter
"This example uses an OutputFilter to replace each tab character
in a code excerpt with an appropritate number of spaces."
^^^^^^^^^^^^^^ ^^^^^^^^^^^^
some text appropriate
(The "code excerpt" to "text" change reads better since there is
no "code excerpt" apparent yet.)
_______________________________
Line-wrapping OutputFilter
"This example uses an OutputFilter to wrap text so that each line
is no longer than a specified maximum value. No attention is
paid to word boundaries."
A little rewording would make this read better:
This example...specified maximum value, ignoring word
boundaries.
_______________________________
Presidential OutputFilter
The political humor of this example is unwarranted in Boost
documentation. Perhaps you could rename it to "Texas
OutputFilter" or "Southern U.S. OutputFilter."
There is no description of what the filter actually does in this
section.
_______________________________
Uncommenting InputFilter
"This example uses an InputFilter to remove shell-style..."
^^^^^
Unix shell
_______________________________
Regex OutputFilter
"This example uses a regex_filter to remove C and C++-style
comments from a code excerpt. Although somewhat more
^^^^^^^^^^^^^^^^^^^
omit
sophisticated than the Uncommenting InputFilter, above, the
^^^
filter in this example is not adequate for use in production..."
^^^^^^^^^^^^^^^^^^^^^^
this filter
_________________________________________________________________
concepts.html
Throughout this page, all references to "resource," "filter,"
etc. should capitalize the words in keeping with their being
concepts.
_______________________________
Overview
"...an InputFilter, which filters input read from a Source, and
an OutputFilter, which filters output written to a Sink."
I suggest a little rephrasing to make this read better and fill
in a couple of gaps:
an InputFilter, which filters input read from a Source or
another InputFilter, and an OutputFilter, which filters output
read from a Source or another OutputFilter, before it is
written to a Sink.
"InputFilters, OutputFilter and their refinements are called..."
^^^^^^^^^^^^
OutputFilters
" In general, a filter or resource may provide access to an input
sequence, for reading, an output sequence, for writing, or both."
^ ^
omit both commas
"The full sets of requirements for the filter and resource
^^^^^^^ ^^^^^^ ^^^^^^^^
set Filter Resource
concepts are summarized in the definitions of the concepts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Resource and Filter which form the roots of the concept..."
^^^^^^^^^^^^^^^^^^^^^^^^^
omit
_______________________________
Resource Concepts
For Source, Sink, InoutResource, and SeekableResource, change
"Provides" to "Resource providing."
"SeekableResource" refers to a read/write "head," but few, if
any, Resources for which this library will be used are physical
devices with read/write heads. I suggest using "location,"
"position," or "offset" in lieu of "head" here and in other parts
of the documentation.
In "SeekableResource," you need a comma between "single" and
"repositional."
_______________________________
Filter Concepts
InputFilter, OutputFilter, InoutFilter, and SeekableFilter refer
to a "stream buffer." Shouldn't they refer to Sources and
Filters instead?
In "SeekableResource," you need a comma between "single" and
"repositional."
_______________________________
Optional Behavior
"Closable: A filter or resource which receives notifications
immediately before a stream is closed"
"Notifications" is unexpected and you refer to a stream. Try
this:
Closable: A Filter or Resource which is told to close
immediately before a Source or Sink is closed.
"Localizable: A filter or resource which receives notifications
when the locale of a stream or stream buffer is set using
basic_ios::imbue or basic_streambuf::pubimbue."
"Notifications" is unexpected and you refer to a stream (buffer).
Try this:
Localizable: a Filter or Resource which is informed when the
locale of a Resource is set using....
In "Direct," you refer to a socket-like interface, but not
everyone will understand what you mean. I suggest using the
phrase, "function-based interface."
_______________________________
Convenience Templates and typedefs
______________
Overview
"They ease the task of defining filters and resources...."
^^^^
"simplify" would read better
"The template resource and its specializations...new resource
types; the template filter and its specializations...new filter
types; the template buffered_filter and its specializations...new
buffered filter types."
Split that into three separate sentences to reduce complexity.
"There are also wide-character versions of these templates,
resource, wfilter..."
^^^^^^^^
namely wresource
_________________________________________________________________
filter.html
_______________________________
Description
"The class template filter, its subcass wfilter...Library to
^^^^^^^
subclass
ease the definitions of new models of the various filter..."
^^^^^^^^^^^^^^^^^^^^^^^
simplify creating
"...Library; they are inteded to be used as base..."
^^^^^^^
intended
_________________________________________________________________
buffered_filter.html
_______________________________
Description
"The class template buffered_filter, its subcass
^^^^^^^
subclass
buffered_wfilter...Library to ease the definitions of new..."
^^^^^^^^^^^^^^^^^^^^^^^
simplify creating
"...Library; they are inteded to be used as base..."
^^^^^^^
intended
_________________________________________________________________
modes.html
_______________________________
Overview
Merge the second paragraph with the first. It's distracting
being separated.
"Readers new to the Iostreams Library should feel free to
^^^^^^^ ^^^^^^^^^^^^
Users omit
concentrate primarly on these two modes."
_______________________________
Definitions of the Modes
"Whether the reading or writing heads are repositionable, and if
so, whether there are separate heads for reading and writing or a
single read/write head."
Rewriting without the use of "head" and correcting the position
of a comma:
Whether the reading or writing locations are repositionaable
and, if so, whether the positions for reading and writing are
separate.
"* Whether a filter or resource is
Closable."
This should be a single line.
Table:
- change "Involves a single sequence" to "A single sequence"
throughout.
- change "Involves a two separate" to "Two separate"
_______________________________
Mode Hierchy Diagrams
^^^^^^^
Hierarchy
The diagram does not translate well to grayscale printing;
there's no apparent difference between the blue and green.
Using arrows, like with UML class diagrams, would make the lines
more meaningful.
_______________________________
Mode Tags
"As with standard library iterator category tags, the tag
corresponding to a mode is convertible to each of the tags
corresponding to modes which the first mode refines."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
of the modes it refines.
"This is useful to help reduce...different of filter types."
^^
omit
You should provide or link to examples that illustrate using some
of the more common modes.
_______________________________
The Metafunction mode
You need to include an example and the signature of mode so we
know how to use it.
_________________________________________________________________
policy_based_streams.html
_______________________________
Overview
"Instances of the policy class can be associated and
^^^
with and
disassociated with an instance of streambuf_facade using..."
^^^^ ^^^^^^^^^^^^^^^^
from a streambuf_facade specialization
"The class template stream_facade is a policy-based stream
template which derives from one of std::basic_istream,
std::basic_ostream and std::basic_iostream depending on the mode
of the policy class. As with streambuf_facade, instances of the
policy class can by associated and disassociated with an instance
of stream_facade using its member functions open and close."
I suggest a few changes to that paragraph to make it more
readable and to correct a few errors:
As a convenience for those needing a stream, the library also
provides the class template stream_facade, which is a
policy-based stream class template. It derives from
std::basic_istream, std::basic_ostream, or
std::basic_iostream, depending upon the mode of the policy
class. As with streambuf_facade, instances of the policy
class can be associated with and dissociated from an instance
of stream_facade using....
_______________________________
Reference
______________
Class template streambuf_facade
______
Description
"Policy-based stream buffer template with an interface...."
^^^^^^^^
class template
______
Synopsis
Using "T" as the name of a policy class template parameter is
confusing. "T" is, of course, commonly used for a data type
stored in a container and for similar purposes. The closest
thing to "T" in streambuf_facade is the "Ch" nested type in the
policy class. Change "T" to a more meaningful name.
______
Template Parameters
"T - A model of the filter or resource concepts. Specializations
of streambuf_facade with filter types are used internally by the
Iostreams Library to construct chains of filters and
resources. Users of the library never need to specialize
streambuf_facade with a filter type."
Since only the library uses filter types for "T", why not name
"T" "Resource" and let the library worry about using filters for
the "Resource" parameter? Also, given that only the library does
this, omit the last two sentences or move them to an Advanced
Topics section.
"Tr - A C++ standard library charatcer traits type ([ISO],
^^^^^^^^^
character
21.1.1) with...the character type Ch of T."
^^^^^^^
T::Ch
"Alloc - A C++ standard library allocator...where Ch is the
^^^
character type of T."
^^^^^^^^^^^^^^^^^^^
T::Ch, the character type in T.
______
streambuf_facade::streambuf_facade
You have two sections with the same heading; both should fall
under the heading "Constructors." Otherwise,
"streambuf_facade::streambuf_facade" should be written as
"streambuf_facade<T,Tr,Alloc,Mode>::streambuf_facade."
______
The first streambuf_facade::streambuf_facade
"Before the instance can be used for i/o, one of its..."
^^^^^^^^
streambuf
______
The second streambuf_facade::streambuf_facade
"Constructs a streambuf_facade which is ready to perform i/o,
where the parameters have the following interpretations:"
^^^^^^^^^^^^^^^
meaning
You don't call out function parameters like this many other
places. There's nothing wrong with it, but you should choose to
explain them in a paragraph or a list and do that throughout the
documentation.
"buffer_size - The size of any buffers that need to be allocated"
In the description of open(), you mention that a size of zero
means that the streambuf is unbuffered. Doesn't that apply here,
too?
"pback_size - The size of the putback buffer, relevant only..."
^^^^^^^
buffer, if any. This is
"The T constructors involved must take all arguments by..."
^^^^^^^^
so invoked
______
streambuf_facade::open
^^
<T,Tr,Alloc,Mode>::
"Assocaites the given instance of T with this instance of
^^^^^^^^^^
Associates
streambuf_facade, if there is no such instance currently
^^^^
T
associated; otherwise, throws std::ios_base::failure. The second
^^^^^^^^^^
associated with this
parameter determines the size of any buffers that need to be
allocated; a value of zero indicates that i/o should be
unbuffered. The third parameter determines the size of the
putback buffer; it is relevant only if Mode is a refinement of
^^^^^^^^^^
buffer, if any. It
"Each of these members associates with this instance of
streambuf_facade a newly constructed instance of the policy type
^^^^^^^^^^^^^^^^^
new
T constructed from the given lists of arguments, if there is no
such instance currently associated; otherwise, they throw
^^^^^^^^^^^^^^^^^^^^^
associated with this. Otherwise
std::ios_base::failure. The T constructors involved must..."
^^^^^^^^
so invoked
______________
Class template stream_facade
______
Examples
Where are the streambuf examples? You said they were the
"fundamental components" of the library.
___
Defining a simple ofstream
^^^^^^
Simple
_________________________________________________________________
filtering_streams.html
_______________________________
Synopsis
There are two, identical declarations of
boost::io::filtering_streambuf.
_________________________________________________________________
adapters.html
_______________________________
Overview
The example references should be by name ("Reading From an STL
Sequence" rather than "Example I.") to make the links more
meaningful.
"2. Filtering stream and stream buffer constructors, as well as
their member functions push, are overloaded...."
^^^^^^^^^^^^^^^^^^^^^
push member functions
_______________________________
Examples
Do any of these techniques apply to filtering_streambufs?
______________
I. Reading from an STL Sequence
^^^^^^^^^^^^^^^
Reading From
______________
II. Overwriting an STL Sequence
^^^^^^^^^^^^^^^
Overwriting
______________
III. Appending to an STL Sequence
^^^^^^^^^^^^^^^
Appending To
"A stream which appends characters to a sequence, say
std::vector, can be defined as follows:"
^^^^^^^^^^^
a std::vector
_________________________________________________________________
code_conversion.html
_______________________________
Overview
"converter: A resource adapter which which takes a resource with
^^^^^^^^^^^
which
a narrow character type and produces a resource with wide
^^^^^^^^^
the corresponding wide
character type by introducing a layer of code conversion
performed using a std::codecvt."
^^^^^^^^^^^^^^^
using
"* converting_streambuf: A wide-character stream buffer template
having an interface essentially identical to
Don't break the paragraph here.
filtering_streambuf, with the following additional property:
after zero or more wide-character filters have been added to the
chain, a sequence of zero or more narrow-character filters and a
narrow character resource may be added. A converter is inserted
automatically between the final wide-character filter and the
first narrow-character filter or resource."
Rephrasing that will simplify it and make it clear:
...essentially identical to filtering_streambuf, which
automatically inserts a converter between the last wide
character filter, if any, and the first narrow character
filter or resource. (Any wide character filters must precede
the narrow character filters and resource in the chain.)
A similar change to the converting_stream paragraph would be
appropriate.
_________________________________________________________________
convenience.html
_______________________________
Overview
You mention a convenience function named "copy" but the only
function shown is operator <<.
_________________________________________________________________
converter.html
_______________________________
Description
"The class templates converter is...and produces a resource with
^^^^^^^^^
template
wide character type"
^^^^
a wide
"If a narrow character resource performs input and output using
two distinct sequences (see Modes),"
^^^^^^^^^^^
omit; you link to inout directly later in the same sentence.
"Otherwise, attempting to spcialize converter results...."
^^^^^^^^^
specialize
_______________________________
Reference
______________
Template parameters
^^^^^^^^^^
Parameters
______________
converter::converter
Calling a constructor a member, however accurate, is odd. Why
not just call it a constructor?
"The third parameter determines the size of the buffers or
^^^^^^^
buffer
buffers used for code conversion."
"The effect of invoking imbue while code conversion...."
^^^^^
Change to use the code typeface
______________
converter::open
"Assocaites the given instance of Resource with this instance of
converter, if there is no such instance currently associated;
otherwise, throws std::ios_base::failure."
"Associates" is misspelled, but rephrasing it would work well:
Makes a copy of the Resource to be used by the converter. If
the converter already has a Resource, it throws
std::ios_base::failure.
I don't think "associates" leaves out an important detail,
suggesting that the Resource is tracked by pointer and that the
Resource's lifetime must extend to the next call to close().
"The third parameter determines the size of the buffer or buffers
used for code conversion."
^^^
for the
______________
converter::close
"Disassociates from this instance of converter any instance of
the resource type Resource currently associated with it, calling
cleanup functions as appropriate and destroying the associated
instance of Resource."
This is awkwardly phrased. I suggest:
Destroys the converter's current Resource, if any, calling the
cleanup functions of any filters and the Resource, as
appropriate.
I don't think "dissociate" (not "disassociates," BTW) is
necessary.
_________________________________________________________________
exceptions.html
_______________________________
The Boost Iostreams Library
______________
Policy
The text is formatted differently than on other pages for this
heading level.
"...implements the protected virtual memeber functions..."
^^^^^^^
member
______________
Rationale
The text is formatted differently than on other pages for this
heading level.
_______________________________
Exception Safety
"1. Resources are freed by calling destructors or
close, if appropriate."
Don't break the line between "or" and "close."
"3.b. ...If the current resource is removed from the chain and a
new one added..."
^^^^^^^^^
one is added
"Conditions 2. and 3. rely on the specification of the filter and
resource concepts. Note that there is no guarantee that a
stream's or stream buffer's character sequences are in a
consistent state, i.e., that data has not been corrupted, and no
way in general to determine the state of these sequences after an
exception."
After reading this paragraph, I'm left to wonder whether removing
and replacing the resource, as described in 3.b, means that the
state of the character buffers is well-defined or still unknown
as described here. IOW, this paragraph seems to contradict 3.b
and should be rephrased to clarify how the state of the buffers
can be known and corrected.
_______________________________
Acknowledgments
"Thanks to Angelika Langer and John Torjo for discussion of
exceptions."
What does "for discussion of exceptions" mean? Did you have
conversations with them on the subject? Then you need to write,
"for our discussions on exceptions and exception handling."
_______________________________
Footnotes
"1...but that "if the exception is rasied due to an error..."
^^^^^^
raised
_________________________________________________________________
regex_filter.html
_______________________________
Description
"The class template basic_regex_filter filters data using regular
expressions the Boost Regular Expression Library."
^^^
via the
"As unfiltered data is scanned for matches, portions of data
^^^^^^^^^^^
the portions of the
which fall between regular expression matches are forwarded
unchanged."
_______________________________
Reference
______________
basic_regex_filter::formatter
"The type of object which a basic_regex_filter uses to...."
^^^
formatter is the
"Since Boost.Function objects are implictly constructible from
function objects with the correct signature, users of regular
expression filters may define their own function objects with the
correct signature and pass them to the basic_regex_filter
constructor..."
This is incomplete. One can write free functions, lambda
functions, etc. that satisfy Boost.Function to create formatters.
______________
basic_regex_filter::basic_regex_filter
Here's another example of the (apparently) less common bulleted
list of parameter descriptions.
"replace - A function which will be passed each match_results
object in succession and whose return values will be be used as
replacement text"
Rewording this will make it clearer:
A Boost.Function object to which each regular expression match
is passed. The return value is used as the filter's result in
lieu of the matched text.
_______________________________
Example
"See Examples."
^^^^^^^^
Regex OutputFilter
_________________________________________________________________
one_step_filter.html
_______________________________
Description
"Its derived classes model DualUseFilter so that it may be used
^^
they?
for either input or output."
_________________________________________________________________
newline_filter.html
_______________________________
Description
"The class templates basic_newline_filter is a DualUseFilter
^^^^^^^^^
template
which converts between the text file formats used by...."
^^^^^^^
among
"Its sole constructor takes an integral flag parameter used to
specify the source and target formats."
I don't see the value of this here. In the description of the
constructor further down the page, this argument is discussed
fully.
"Note: It is not known if specializations of basic_newline_filter
other than basic_newline_filter<char> are useful. If not, the
template parameter will be eliminated."
Make this a footnote referenced from "Ch" in the Template
Parameters section.
_______________________________
basic_newline_filter::basic_newline_filter
You misspelled "interpreted" in the table several times.
_________________________________________________________________
compression.html
_______________________________
Acknowlegments
"The compression/decompression filters were influences by the..."
^^^^^^^^^^
influenced
"Thanks also to Jean-loup Gailly and Mark Adler and to Julian
^^^^^^^^^^^^^^^^^^^^^^
, Mark Adler and
Seward for making their excellent librarys available..."
^^^^^^^^
libraries
_______________________________
Installation
"Alternatively, the binaries can be build from the source code."
^^^^^
built
_________________________________________________________________
file_based_resources.html
_______________________________
Overview
"...access to memory-mapped files on Windows an POSIX."
^^
and
_______________________________
Acknowledgments
"The memory-mapped file resources are based on work of Craig..."
^^
on the
_________________________________________________________________
file.html
_______________________________
Reference
______________
Class template basic_file_source
^^^^^^^^
Template
______
basic_file_source::basic_file_source
"Constructs...std::basic_filebuf buf opened as follows:"
^^^
but
______________
Class template basic_file_sink
^^^^^^^^
Template
______
basic_file_sink::basic_file_sink
"Constructs...std::basic_filebuf buf opened as follows:"
^^^
but
______________
Class template basic_file_resource
^^^^^^^^
Template
______
basic_file_resource_::basic_file_resource
^^^^^^^^^
resource
"Constructs...std::basic_filebuf buf opened as follows:"
^^^
but
_________________________________________________________________
text_processing.html
_______________________________
Overview
"The...provides two types of filters for test processing:"
^^^^
text
_________________________________________________________________
rationale.html
_______________________________
Design Decisions
______________
Generic Design
"2. The library can be easily extended to handle..."
^^^^^^^^^^^^^^^^^^^^^^
can be extended easily (avoids split infinitive)
"reduce code bloat by internally wrapping filters and resources
in polymorphic classes with virtual function read, write,
^^^^^^^^
functions
etc. without a noticable performance impact."
^^^^^^^^^
noticeable
______________
Chain Interface
"If there is a need for it, it can easily be restored."
^^^^^^^^^^^^^^^^^^^^^^
can be restored easily (avoids split infinitive)
______________
Return Type of write
"...cannot be written, was adopter for these reasons:"
^^^^^^^
adopted
_______________________________
Planned Changes
"2. The concept Buffered will be renamed MultiCharacter, since it
is more descriptive and Buffered would be better used elsewhere."
I don't understand this point. "MultiCharacter" does not convey
anything useful. Even an unbuffered filter processes multiple
characters. "Buffered" seems to convey the right idea. More
detail is needed about where you would prefer to use "Buffered"
and more consideration of what to call what is now called
"Buffered" is needed.
"3. ...The concept of a smart resources, which already..."
^^^^^^^^^^^^^^^^^
a smart resource -OR- smart resources
"4. ...This is necessary to accommodate i/o models just as..."
^^^^
such?
"1. Adopt the convention that reads and writes always block until
at least one character is written."
^^^^^^^
transferred
_________________________________________________________________
portability.html
_______________________________
Overview
"...together with a coresponding Jamfile."
^^^^^^^^^^^^
corresponding
_________________________________________________________________
installation.html
_______________________________
Overview
"4. ...and depend on the non-boost library"
^^^^^
Boost
" 5. ...and depend on the non-boost library"
^^^^^
Boost
_________________________________________________________________
adapt.html
_______________________________
Overview
"The overloaded function template adapt takes an OutputIterator,
a pair of ForwardIterators or a standard i/o stream or stream
buffer and returns a resource."
The series is confusing as written; I suggest:
The overloaded function template adapt takes an
OutputIterator, a pair of ForwardIterators, a
std::basic_iostream, or a std::basic_streambuf, and returns a
resource.
_______________________________
Reference
______________
adapt - Iterator Ranges
______
Template Parameters
"Source - A model of ForwardIterator."
^^^^^^
FwdIt
______
Return Value
"Returns a Resource...delimited by first and last."
^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is probably well understood by all readers, but it might be
better to express this more formally.
_________________________________________________________________
back_inserter.html
Broken link to
<http://home.comcast.net/~jturkanis/iostreams/libs/io/doc/functions/classes/back_inserter.html#synopsis>
_________________________________________________________________
close.html
_______________________________
Description
"This gives filters and resources an opportunity to free
resources or reset their states in preparation for a fresh..."
^^^^^^
state
_______________________________
When is close invoked?
It is premature to discuss the invocations of close() without
showing its synopsis. You should put the synopsis just after the
Description section.
______________
streambuf_facade and stream_facade
This section is a bit confusing. First you say that r.close()
calls boost::io::close(r, std::ios_base::in) followed by
boost::io::close(r, std::ios_base::out). Then, you say that if
"r" controls a single sequence, those calls wind up, in effect at
least, calling r.close().
______________
filtering_streambuf and filtering_stream
You used the term "complete" here. I recall it being defined
elsewhere, but it would be useful if you had a single point of
definition to which you could link whenever you mention it.
The sequence of close() calls never mentions buf1. Is there a
mistake? If not, some clarification is in order.
"...each element receives two closure notifications..."
^^^^^^^^^^^^^^^^^^^^^
calls to close
_______________________________
Reference
______________
Synopsis
You've used "T" to mean a Resource in one case and a Filter in
the other. This is confusing. You should use consistent
parameter names among all of the library templates.
_________________________________________________________________
copy.html
_______________________________
Description
"The function template copy reads data from a given model of
Source - or from a standard input stream or stream buffer - and
writes it to a given model of Sink - or from a standard output
stream or stream buffer - until the end of stream is reached."
This sentence is confusing due to the number of hypenated
phrases. If I've got it right, it should be written like this:
The function template copy reads data from a model of Source,
which might be a std::basic_istream or std::basic_streambuf,
and writes the data to a model of Sink, which might be a
std::ostream or std::streambuf, until the end of the input
stream.
"The size of the temporary buffer used may be supplied..."
^^^^^^^^^^^^^^^^
temporary buffer between the input and output streams
_________________________________________________________________
get.html
_______________________________
Reference
______________
Description
On many pages, "Description" is the topmost section. Here, it's
a subsection of "Reference." Why? This section duplicates the
information provided in the Overview, so one of them is
superfluous. (This applies to many pages.)
"Attemps to extract a character from a given instance..."
^^^^^^^
Attempts
______________
Template Parameters
"Source - A...or a standard input stream or stream buffer type."
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
Why not just write "std::basic_istream" and
"std::basic_streambuf?" (This applies to many pages.)
______________
Return Type
If the return type is known to be "typename
std::char_traits<typename char_type<Source>::type>::int_type" why
not just show that as the return type in the synopsis?
_________________________________________________________________
imbue.html
_______________________________
Description
"Alothugh imbue is designed to be overloaded..."
^^^^^^^^
Although
_________________________________________________________________
read.html
_______________________________
Overview
"The first overload.... The second overload...."
No overloads have yet been shown, so this is premature. Move
these sentences to Reference|Semantics.
_______________________________
Example
An example is premature when you haven't shown the synopsis or
described the parameters. IOW, this section should follow the
Reference section.
_______________________________
Reference
______________
Description
On many pages, "Description" is the topmost section. Here, it's
a subsection of "Reference." Why? This section duplicates the
information provided in the Overview, so one of them is
superfluous.
______________
Synopsis
The second overload extends past the screen, depending upon the
text size.
______________
Template Parameters
"T - For the first overload, a model of Source or a standard
input stream or stream buffer type. For the second overload, a
model of InputFilter."
The fact that you must describe the parameter this way is a clear
indication that you need to use better parameter names. How
about:
template<typename Resource>
std::streamsize read(Resource& t, ...);
template<typename InputFilter, typename Source>
std::streamsize read(InputFilter& t, Source& src, ...);
Since the definition of "Source" refers to T's character type,
you'll have to make reference to Resource's or InputFilter's
character type. With these distinctions in place, the subsequent
Semantics sections won't need to replicate the declarations.
_________________________________________________________________
reverse.html
_______________________________
Description
"The function template reverse takes a filter and returns a new
filter which performs the same filtering operation as the
original filter but which is an OutputFilter if the orginal
filter was an InputFilter and and InputFilter if the orginal
filter was an OutputFilter. Roughly speaking, it reverses the
direction of a given filter."
The ideas here are conveyed in the wrong order and why, "roughly
speaking?"
The function template reverse reverses the filtering direction
of a given filter. It turns an InputFilter into an
OutputFilter and an OutputFilter into an InputFilter.
You mention memory overhead that can be a side effect of using
reverse(). Are there performance issues as well? Also,
shouldn't that paragraph be set off with "Note:" or "Warning:"?
You mention that using reverse may not be suitable for some data
streams, but you need to give more guidance regarding why one
would want to use reverse().
_________________________________________________________________
seek.html
_______________________________
Overview
"The function template seek is used by the Iostreams Library to
perform random access withing a sequence controlled by a..."
^^^^^^^
within
"seek is designed...specialized for resource types external..."
^^^^^^^^
Resource
_______________________________
Reference
______________
Template Parameters
"...A model of one of the resource concepts which..."
^^^^^^^^
Resource
______________
Function Parameters
"way - ..."
You refer to std::ios_base::beg twice. The latter should be
std::ios_base::end. Also, "way" would be better named "dir" or
"direction," don't you think?
_________________________________________________________________
write.html
The same comments apply to this page as to read.html, above.
_________________________________________________________________
io_traits.html
_______________________________
Overview
"The header <boost/io/categories.hpp> contains category tags for
classifying models of the various filter and resource concepts."
^^^^^^ ^^^^^^^^
Filter Resource
"The header <boost/io/io_traits.hpp> contains the definitions of
the metafunctions char_type and category, used to associate two
fundamental types with each model of one the filter or resource
concepts:"
I'm not quite sure how the end of that sentence should be
phrased, but it's confusing as is. Perhaps this conveys the
right information clearly:
...used to determine the type of characters processed by, and
the category, or capability description, of Filters and
Resources.
______________
Character Type
This section seems out of place. It should be titled,
"char_type," but you haven't introduced that template yet. I
suggest that this descriptive text be moved to the Class Template
char_type|Description section.
______________
Category
This section, too, is out of place. I suggest moving the content
to Class Template category|Description.
_______________________________
Class Template char_type
______________
Description
"Metafunction associating a character type to each filter or
resource type."
char_type is a metafunction associating a character type with
a Filter or Resource type. The result is the character type
the Filter or Resource reads and/or writes.
(I merged your original with the earlier Character Type section
text and rephrased the result.)
______________
Template parameters
^^^^^^^^^^
Parameters
"T - A model of one of the filter or resource concepts, or a
standard stream or stream buffer"
As in other places, capitalize "filter" and "resource" when
referring to them as concepts.
_______________________________
io_traits::type
Where did this come from? I don't understand how io_traits::type
is related to char_type (without looking at the code, of course).
_______________________________
Class Template category
______________
Description
"Metafunction associating a category tag to each filter or
resource type."
category is a metafunction that associates a category tag with
each Filter or Resource type. The category indicates whether
the type is a Filter or Resource, what the type's mode is, and
what optional behavior the type provides. The category is
similar to the iterator_category member of
std::iterator_traits. Types which represent categories are
called category tags.
(I merged your original with the earlier Category section text,
and rephrased the result.)
_______________________________
Category Tags
"...simply define a struct extending the existing tags."
^^^^^^^^^
(multiply) derived from
The table doesn't which tags are mutually exclusive. Is that
exclusivity enforced? For example, a type cannot be both a
Filter and a Resource, so only one of filter_tag and resource_tag
may be used to create a legitimate category. Is that enforced?
Is a category tag validated in any way? That is, what if a
developer specifies neither filter_tag nor resource_tag. Is the
category tag still valid, will it produce a meaningful error, or
will it wreak havoc?
_________________________________________________________________
mode.html
_______________________________
Description
"Metafunction returning a mode tag corresponding the the mode of
a model of one of the filter or resource concepts or of a
standard stream or stream buffer."
mode is a metafunction that determines the mode type that
indicates the mode of the Filter or Resource. The mode can
indicate whether the type is usable for input, output, or
both, and whether and how the type supports seeking.
_________________________________________________________________
filtering_stream.html
_______________________________
Description
"Standard stream template used for filtering data."
filtering_stream is a standard stream template used for
filtering data.
_______________________________
Reference
In the function sections, you don't separate descriptions of
template parameters from those of function parameters. While it
does make things consume more space, I think "Template
Parameters" and "Function Parameters" headings would be helpful.
______________
Template parameters
^^^^^^^^^^
Parameters
"Tr - The traits type"
You should mention that std::char_traits<Ch> is the default for
this parameter (it's in the synopsis, of course, but it bears
repeating). You should also document which features of the
traits class you need so folks that want to write their own can.
(You might capture this information in one place to reference
from multiple places.)
______________
filtering_stream::filtering_stream
This heading is repeated several times because there are several
constructors. It would be better to preface them all with one
heading, "Constructors."
______________
filtering_stream::filtering_stream (#2)
"t - An instance of T"
This description is not helpful. I can see what it is from the
synopsis. Perhaps:
The initial Filter or Resource in the filtering_stream.
"The parameters have the following interpretations:"
^^^^^^^^^^^^^^^
meaning
______________
filtering_stream::filtering_stream (#3)
There's no parameter list introductory statement like, "The
parameters have the following meaning."
The parameter list doesn't describe "t" as did the second.
______________
filtering_stream::filtering_stream (#4)
The description leaves me wanting more. IIUC, this creates a
complete filtering_stream with no Filters that uses an iterator
based Resource. For input, that would mean that only the
characters in the range [first, last) are read. For output, that
would mean that characters are written through *first++ until
first == last. If I've gotten that right, you need to say
something like that so no one else must deduce the same
information. Also, this filtering_stream would be complete,
right?
There's no parameter list introductory statement like, "The
parameters have the following meaning." In fact, you've been
inconsistent in this on many pages. However, adding a "Function
Parameters" heading should be sufficient in and of itself.
______________
filtering_stream::push (#1)
"T - A CopyConstructible model..."
You should reference a footnote that contains the information
that follows regarding using boost::ref, etc. (That is, move
that information to a footnote and then reference it from here.)
You'll need to do this elsewhere, too.
"t - An instance of T"
Can you describe this better?
______________
filtering_stream::push (#1)
Parameter "t" is not in the parameters description list.
______________
filtering_stream::push (#2)
The signature of this function is identical to the previous push
overload. Thus, you should merge the two in the synopsis and
when documenting them.
______________
filtering_stream::push (#3)
"Iter - An iterator type...Ch and whose traveral..."
^^^^^^^^
traversal
______________
filtering_stream::pop
"If the chain is initially complete, causes..."
^^^^^^^^^^^^^^^^^^^^^
was complete prior to calling pop
______________
filtering_stream::emtpy
"Returns true if the underlying chain is empty."
^^^^^^^^
contains no Filters or Resources.
______________
filtering_stream::size
"Returns the number of stream buffers in the underlying chain."
^^^^^^^^^^^^^^
Should that be "Filters and the Resource, if any?"
______________
filtering_stream::reset
"Clears the underlying chain. If the chain is initially complete,
causes"
If I understand correctly, that should be worded more like this:
If the chain was complete before calling reset, it closes and
releases all Filters in the underlying chain. In either case,
it closes and releases the Resource, if any.
_________________________________________________________________
filtering_streambuf.html
Many of the filtering_stream.html comments apply.
-- Rob Stewart stewart_at_[hidden] Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk