mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 13:45:04 +02:00
JsonEncoder: wrap writer for flushing
This commit intruduces a small helper class that wraps any writer and provides a flush operation that performs the corresponding action if the writer is an AsyncJsonWriter and does nothing otherwise.
This commit is contained in:
parent
82b80e24c1
commit
1f15f0ff07
@ -24,7 +24,7 @@ JsonEncoder::JsonEncoder(std::basic_ostream<char>& stream, bool prettify)
|
||||
}
|
||||
|
||||
JsonEncoder::JsonEncoder(nlohmann::detail::output_adapter_t<char> w, bool prettify)
|
||||
: m_IsAsyncWriter{dynamic_cast<AsyncJsonWriter*>(w.get()) != nullptr}, m_Pretty(prettify), m_Writer(std::move(w))
|
||||
: m_Pretty(prettify), m_Writer(std::move(w)), m_Flusher{m_Writer}
|
||||
{
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ void JsonEncoder::EncodeArray(const Array::Ptr& array, boost::asio::yield_contex
|
||||
WriteSeparatorAndIndentStrIfNeeded(!isEmpty);
|
||||
isEmpty = false;
|
||||
Encode(item, yc);
|
||||
FlushIfSafe(yc);
|
||||
m_Flusher.FlushIfSafe(yc);
|
||||
}
|
||||
EndContainer(']', isEmpty);
|
||||
}
|
||||
@ -134,7 +134,7 @@ void JsonEncoder::EncodeValueGenerator(const ValueGenerator::Ptr& generator, boo
|
||||
WriteSeparatorAndIndentStrIfNeeded(!isEmpty);
|
||||
isEmpty = false;
|
||||
Encode(*result, yc);
|
||||
FlushIfSafe(yc);
|
||||
m_Flusher.FlushIfSafe(yc);
|
||||
}
|
||||
EndContainer(']', isEmpty);
|
||||
}
|
||||
@ -171,7 +171,7 @@ void JsonEncoder::EncodeObject(const Iterable& container, const ValExtractor& ex
|
||||
Write(m_Pretty ? ": " : ":");
|
||||
|
||||
Encode(extractor(val), yc);
|
||||
FlushIfSafe(yc);
|
||||
m_Flusher.FlushIfSafe(yc);
|
||||
}
|
||||
EndContainer('}', isEmpty);
|
||||
}
|
||||
@ -223,29 +223,6 @@ void JsonEncoder::EncodeNumber(double value) const
|
||||
EncodeNlohmannJson(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the output stream if it is safe to do so.
|
||||
*
|
||||
* Safe flushing means that it only performs the flush operation if the @c JsonEncoder has not acquired
|
||||
* any object lock so far. This is to ensure that the stream can safely perform asynchronous operations
|
||||
* without risking undefined behaviour due to coroutines being suspended while the stream is being flushed.
|
||||
*
|
||||
* When the @c yc parameter is provided, it indicates that it's safe to perform asynchronous operations,
|
||||
* and the function will attempt to flush if the writer is an instance of @c AsyncJsonWriter.
|
||||
*
|
||||
* @param yc The yield context to use for asynchronous operations.
|
||||
*/
|
||||
void JsonEncoder::FlushIfSafe(boost::asio::yield_context* yc) const
|
||||
{
|
||||
if (yc && m_IsAsyncWriter) {
|
||||
// The m_IsAsyncWriter flag is a constant, and it will never change, so we can safely static
|
||||
// cast the m_Writer to AsyncJsonWriter without any additional checks as it is guaranteed
|
||||
// to be an instance of AsyncJsonWriter when m_IsAsyncWriter is true.
|
||||
auto ajw(static_cast<AsyncJsonWriter*>(m_Writer.get()));
|
||||
ajw->MayFlush(*yc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a string to the underlying output stream.
|
||||
*
|
||||
@ -313,6 +290,36 @@ void JsonEncoder::WriteSeparatorAndIndentStrIfNeeded(bool emitComma) const
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps any writer of type @c nlohmann::detail::output_adapter_t<char> into a Flusher
|
||||
*
|
||||
* @param w The writer to wrap.
|
||||
*/
|
||||
JsonEncoder::Flusher::Flusher(const nlohmann::detail::output_adapter_t<char>& w)
|
||||
: m_AsyncWriter(dynamic_cast<AsyncJsonWriter*>(w.get()))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the underlying writer if it supports that operation and is safe to do so.
|
||||
*
|
||||
* Safe flushing means that it only performs the flush operation if the @c JsonEncoder has not acquired
|
||||
* any object lock so far. This is to ensure that the stream can safely perform asynchronous operations
|
||||
* without risking undefined behaviour due to coroutines being suspended while the stream is being flushed.
|
||||
*
|
||||
* When the @c yc parameter is provided, it indicates that it's safe to perform asynchronous operations,
|
||||
* and the function will attempt to flush if the writer is an instance of @c AsyncJsonWriter. Otherwise,
|
||||
* this function does nothing.
|
||||
*
|
||||
* @param yc The yield context to use for asynchronous operations.
|
||||
*/
|
||||
void JsonEncoder::Flusher::FlushIfSafe(boost::asio::yield_context* yc) const
|
||||
{
|
||||
if (yc && m_AsyncWriter) {
|
||||
m_AsyncWriter->MayFlush(*yc);
|
||||
}
|
||||
}
|
||||
|
||||
class JsonSax : public nlohmann::json_sax<nlohmann::json>
|
||||
{
|
||||
public:
|
||||
|
@ -81,8 +81,6 @@ private:
|
||||
void EncodeNlohmannJson(const nlohmann::json& json) const;
|
||||
void EncodeNumber(double value) const;
|
||||
|
||||
void FlushIfSafe(boost::asio::yield_context* yc) const;
|
||||
|
||||
void Write(const std::string_view& sv) const;
|
||||
void BeginContainer(char openChar);
|
||||
void EndContainer(char closeChar, bool isContainerEmpty = false);
|
||||
@ -91,7 +89,6 @@ private:
|
||||
// The number of spaces to use for indentation in prettified JSON.
|
||||
static constexpr uint8_t m_IndentSize = 4;
|
||||
|
||||
const bool m_IsAsyncWriter; // Whether the writer is an instance of AsyncJsonWriter.
|
||||
bool m_Pretty; // Whether to pretty-print the JSON output.
|
||||
unsigned m_Indent{0}; // The current indentation level for pretty-printing.
|
||||
/**
|
||||
@ -104,6 +101,20 @@ private:
|
||||
|
||||
// The output stream adapter for writing JSON data. This can be either a std::ostream or an Asio stream adapter.
|
||||
nlohmann::detail::output_adapter_t<char> m_Writer;
|
||||
|
||||
/**
|
||||
* This class wraps any @c nlohmann::detail::output_adapter_t<char> writer and provides a method to flush it as
|
||||
* required. Only @c AsyncJsonWriter supports the flush operation, however, this class is also safe to use with
|
||||
* other writer types and the flush method does nothing for them.
|
||||
*/
|
||||
class Flusher {
|
||||
public:
|
||||
explicit Flusher(const nlohmann::detail::output_adapter_t<char>& w);
|
||||
void FlushIfSafe(boost::asio::yield_context* yc) const;
|
||||
|
||||
private:
|
||||
AsyncJsonWriter* m_AsyncWriter;
|
||||
} m_Flusher;
|
||||
};
|
||||
|
||||
String JsonEncode(const Value& value, bool prettify = false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user