|
JSON Voorhees
Killer JSON for C++
|
A writer instance writes a JSON ast_node sequence to some form of sink: an encoder, which turns the tokens into text or into whatever else it builds.
More...
#include <jsonv/writer.hpp>
Public Member Functions | |
| writer (encoder &to) | |
| Create a writer which writes into to. The encoder must outlive this instance. | |
| writer (std::ostream &to) | |
Create a writer which writes compact JSON text into to, as to_string does for a value: through an ostream_encoder it owns, with ostream_encoder::ensure_ascii on. | |
| writer (const writer &)=delete | |
| writer & | operator= (const writer &)=delete |
| bool | good () const noexcept |
| Check if this writer is still good to write to, which is to say that it has not been moved-from. | |
| std::size_t | depth () const noexcept |
| The number of structures – objects and arrays – currently open. | |
| const path & | current_path () const |
| Get the path of the slot the next token fills. | |
| writer & | key (std::string_view key) |
| Write the key of the next member of the open object, including the separator. | |
| writer & | write (const value &source) |
Write the whole of source as one value, as encoder::encode does. | |
| writer & | write (value &&source) |
| Write the whole of source as one value, handing it over to the sink. | |
| writer (writer &&) noexcept | |
Moving a writer transfers its state and its sink, leaving the source moved-from: good is false, depth is 0 and every other member throws std::invalid_argument. | |
| writer & | operator= (writer &&) noexcept |
Moving a writer transfers its state and its sink, leaving the source moved-from: good is false, depth is 0 and every other member throws std::invalid_argument. | |
| writer & | object_begin () |
| Write the token which opens or closes an object or an array. | |
| writer & | object_end () |
| Write the token which opens or closes an object or an array. | |
| writer & | array_begin () |
| Write the token which opens or closes an object or an array. | |
| writer & | array_end () |
| Write the token which opens or closes an object or an array. | |
| writer & | null () |
| Write a scalar value. | |
| writer & | boolean (bool value) |
| Write a scalar value. | |
| writer & | integer (std::int64_t value) |
| Write a scalar value. | |
| writer & | decimal (double value) |
| Write a scalar value. | |
| writer & | string (std::string_view value) |
| Write a scalar value. | |
A writer instance writes a JSON ast_node sequence to some form of sink: an encoder, which turns the tokens into text or into whatever else it builds.
This is the mirror of reader. A reader is a forward cursor over the tokens of a document somebody else wrote; a writer is a forward cursor over the tokens of the document you are writing. Each token method writes one token and returns *this, so calls chain. Writing an object means opening it, writing each member as a key followed by its value, and closing it:
The writer owns the grammar and the punctuation. It refuses a token the grammar does not allow where the cursor is – a key outside an object, a value in an object with no key before it, an end which does not match the open structure – with std::logic_error, before the sink sees anything; and it writes the delimiters between elements and between members itself, so an encoder only ever sees a sequence of tokens which spells a valid document. A writer at depth zero accepts another root value, which is how two documents end up in one stream.
Definition at line 67 of file writer.hpp.
|
explicit |
Create a writer which writes compact JSON text into to, as to_string does for a value: through an ostream_encoder it owns, with ostream_encoder::ensure_ascii on.
To pretty-print, or to write well-formed UTF-8 as it is, construct the encoder yourself and use the overload above. The stream must outlive this instance.
|
noexcept |
Moving a writer transfers its state and its sink, leaving the source moved-from: good is false, depth is 0 and every other member throws std::invalid_argument.
These are out-of-line because destroying the state needs a complete writer::impl, which this header does not have – the same reason the destructor is.
| writer & jsonv::writer::array_begin | ( | ) |
Write the token which opens or closes an object or an array.
Opening one is writing a value, so it is allowed wherever a value is: at depth zero, as an array element, or as the value of the key just written. Closing one must match the innermost open structure, and an object cannot close while a key is waiting for its value.
| std::logic_error | if the grammar does not allow the token here. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::array_end | ( | ) |
Write the token which opens or closes an object or an array.
Opening one is writing a value, so it is allowed wherever a value is: at depth zero, as an array element, or as the value of the key just written. Closing one must match the innermost open structure, and an object cannot close while a key is waiting for its value.
| std::logic_error | if the grammar does not allow the token here. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::boolean | ( | bool | value | ) |
Write a scalar value.
A value is allowed at depth zero, as an array element, or as the value of the key just written. What a decimal with no JSON representation – a NaN or an infinity – becomes is the encoder's choice, as is what happens to a string which is not valid UTF-8 (see encoder::write_decimal and encoder::write_string).
| std::logic_error | if an object is open and no key is waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| const path & jsonv::writer::current_path | ( | ) | const |
Get the path of the slot the next token fills.
This is where a serializer is when it finds it cannot write the value it was asked for, which is what the path is for. It is built from the stack of open structures on demand and kept until the next token, so a document which never asks never pays for it – unlike reader::current_path over text, which rescans the document. The convention differs from the reader's, which names the token it is on: a reader on an element and a writer about to write that element agree, as do the two at a key, while a reader on a closing token names the structure it closes and a writer which has just closed one names where its next token goes.
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::decimal | ( | double | value | ) |
Write a scalar value.
A value is allowed at depth zero, as an array element, or as the value of the key just written. What a decimal with no JSON representation – a NaN or an infinity – becomes is the encoder's choice, as is what happens to a string which is not valid UTF-8 (see encoder::write_decimal and encoder::write_string).
| std::logic_error | if an object is open and no key is waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
|
noexcept |
The number of structures – objects and arrays – currently open.
This is 0 before the first token, between root values, and for a moved-from writer.
| writer & jsonv::writer::integer | ( | std::int64_t | value | ) |
Write a scalar value.
A value is allowed at depth zero, as an array element, or as the value of the key just written. What a decimal with no JSON representation – a NaN or an infinity – becomes is the encoder's choice, as is what happens to a string which is not valid UTF-8 (see encoder::write_decimal and encoder::write_string).
| std::logic_error | if an object is open and no key is waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::key | ( | std::string_view | key | ) |
Write the key of the next member of the open object, including the separator.
The value must follow before the next key or the end of the object. key is viewed, not kept: it has to live until this returns and no longer.
| std::logic_error | if no object is open, if the innermost open structure is an array, or if the key before this one is still waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::null | ( | ) |
Write a scalar value.
A value is allowed at depth zero, as an array element, or as the value of the key just written. What a decimal with no JSON representation – a NaN or an infinity – becomes is the encoder's choice, as is what happens to a string which is not valid UTF-8 (see encoder::write_decimal and encoder::write_string).
| std::logic_error | if an object is open and no key is waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::object_begin | ( | ) |
Write the token which opens or closes an object or an array.
Opening one is writing a value, so it is allowed wherever a value is: at depth zero, as an array element, or as the value of the key just written. Closing one must match the innermost open structure, and an object cannot close while a key is waiting for its value.
| std::logic_error | if the grammar does not allow the token here. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
| writer & jsonv::writer::object_end | ( | ) |
Write the token which opens or closes an object or an array.
Opening one is writing a value, so it is allowed wherever a value is: at depth zero, as an array element, or as the value of the key just written. Closing one must match the innermost open structure, and an object cannot close while a key is waiting for its value.
| std::logic_error | if the grammar does not allow the token here. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
Moving a writer transfers its state and its sink, leaving the source moved-from: good is false, depth is 0 and every other member throws std::invalid_argument.
These are out-of-line because destroying the state needs a complete writer::impl, which this header does not have – the same reason the destructor is.
| writer & jsonv::writer::string | ( | std::string_view | value | ) |
Write a scalar value.
A value is allowed at depth zero, as an array element, or as the value of the key just written. What a decimal with no JSON representation – a NaN or an infinity – becomes is the encoder's choice, as is what happens to a string which is not valid UTF-8 (see encoder::write_decimal and encoder::write_string).
| std::logic_error | if an object is open and no key is waiting for its value. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
Write the whole of source as one value, as encoder::encode does.
An encoder producing text walks it, writing every node in order with an object's members in the order the object keeps them, which is sorted by key; one which builds a tree copies it as it is rather than rebuilding it node by node.
| std::logic_error | if a value is not allowed here, as for the scalar functions. Nothing has reached the sink. |
| std::invalid_argument | if this instance has been moved-from. |
Write the whole of source as one value, handing it over to the sink.
An encoder which builds a tree takes it as it is rather than copying it, and one producing text walks it exactly as the overload above does. source is left moved-from.
| std::logic_error | if a value is not allowed here, as for the scalar functions. Nothing has reached the sink and source is untouched. |
| std::invalid_argument | if this instance has been moved-from. |