Subject: Re: [SG16-Unicode] std::byte based I/O library
From: JeanHeyd Meneide (phdofthehouse_at_[hidden])
Date: 2019-02-14 19:46:10
Apologies for the delay. I think the point I'm trying to make is that
your stream type should not include the state at all. Perhaps, I should
back up a bit:
- The serializer type you have can include whatever it wants to
perform the serialization (including (or not!) locale or whatever other
state is necessary)
- The *stream* type must not -- MUST not -- include anything about
serialization or text or whatever.
The only operations the stream type has is "std::io::read( stream,
buffer, length )" and "std::io::write( stream, bytes, length )". Everything
else on the stream object should be for the sole purpose of supporting
those 2 operations, and literally nothing else. (Maybe async versions as
From there, you stack on what you need on the serializer type. As an
std::io::stream s( ... );
std::cool_serializer user_interactable( s, whatever, you, want );
Note the proper separation of concerns. Now, stream has one job and
one job only: writing and reading bytes. The serializer can be made to have
all the customization points in the world, all the state it wants, and all
the functionality, but now none of it gets in the way of whatever the
stream object is supposed to be doing. The serializer's only job is to ask
things that get serialized:
int variable = ...;
int variable = user_interactable.read<int>();
std::text variable2 = user_interactable.read<std::text>();
You can add custom operators to the thing that's meant to be
user_interactable: the stream. You can add encoding information.
Customization points. Locales (or not). Anything your heart desires. It
calls std::io::write(_my_s, my_serialized_int_bytes, length ); and
std::io::read( buffer, maximum_lengths ); before passing the read bytes to
serializer_customization_point<std::text>( buffer, read_length );
underneath (as an example). Now, concerns are separated: the IO stream is
good at doing IO. And the serializer stream is good at serializing.
Well-separated. Easy to optimize. You can even do things like pass the
memory mapped data directly to the serializer's customization point, if
that's the goal. But whatever you do...
Keep the stream clean. Keep it transparent, make it safe to use, do
not put state in it.
Do not muddy its waters.
On Thu, Feb 7, 2019 at 2:59 PM Lyberta <lyberta_at_[hidden]> wrote:
> > There should be no "text IO". Binding attributes on stream objects
> > "handle text" is the mistake IO streams made; it absolutely muddled the
> > concerns of IO streams and turned them into stateful messes on the same
> > level of floating point and having to save / restore FP registers after
> > each call or specific use in order to not break everything downstream /
> > used after you made a few calls with specific "sticky" flags.
> So do you want to pass the state explicitly such as
> std::io::read(stream, state, variable);
> My idea is a bit of compromise that I put everything in a single object
> and provide a simple accessor function to change it such as
> auto my_state = stream.state();
> // ...
> // Change state
> // ...
> stream.state() = my_state;
> That way we still have the convenient syntax of
> std::io::read(stream, variable);
> > If you want IO in your text library, make it a single, atomic call
> > where all the information required to serialize the text properly is done
> > in a single function.
> I'm totally fine with this design but I wonder if anyone actually has a
> use case where they can't just parse all the text into string at once.
> But I'm fine with skipping this use case for now.
> SG16 Unicode mailing list
SG16 list run by herb.sutter at gmail.com