diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-07-06 02:03:50 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-07-06 02:27:46 +0200 |
| commit | 17f0b0b3bc65ffba39bf6f22a12b2cc7fcb9bafd (patch) | |
| tree | 5993d701145e2117fb8598faa186312b98d54f00 /src | |
| parent | 1da55c8be619a21153845607a553c9d1206bc792 (diff) | |
| download | PROJ-17f0b0b3bc65ffba39bf6f22a12b2cc7fcb9bafd.tar.gz PROJ-17f0b0b3bc65ffba39bf6f22a12b2cc7fcb9bafd.zip | |
Proof-of-concept of JSON export limited to PrimeMeridian (refs #1545)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 6 | ||||
| -rw-r--r-- | src/iso19111/common.cpp | 65 | ||||
| -rw-r--r-- | src/iso19111/datum.cpp | 35 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 87 | ||||
| -rw-r--r-- | src/iso19111/metadata.cpp | 20 | ||||
| -rw-r--r-- | src/lib_proj.cmake | 2 | ||||
| -rw-r--r-- | src/proj_json_streaming_writer.cpp | 297 | ||||
| -rw-r--r-- | src/proj_json_streaming_writer.hpp | 145 |
8 files changed, 655 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index aed5a393..e50a5638 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \ AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@ include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesic.h \ - org_proj4_PJ.h proj_symbol_rename.h + org_proj4_PJ.h proj_symbol_rename.h proj_json_streaming_writer.hpp EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \ bin_geod.cmake bin_proj.cmake bin_projinfo.cmake \ @@ -208,7 +208,9 @@ libproj_la_SOURCES = \ wkt1_parser.h wkt1_parser.cpp \ wkt1_generated_parser.h wkt1_generated_parser.c \ wkt2_parser.h wkt2_parser.cpp \ - wkt2_generated_parser.h wkt2_generated_parser.c + wkt2_generated_parser.h wkt2_generated_parser.c \ + \ + proj_json_streaming_writer.cpp # The sed hack is to please MSVC diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp index d46da0da..f2a51032 100644 --- a/src/iso19111/common.cpp +++ b/src/iso19111/common.cpp @@ -236,6 +236,54 @@ void UnitOfMeasure::_exportToWKT( } formatter->endNode(); } + +// --------------------------------------------------------------------------- + +void UnitOfMeasure::_exportToJSON( + JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + PROJ::CPLJSonStreamingWriter::ObjectContext objContext(writer); + writer.AddObjKey("type"); + const auto l_type = type(); + if (l_type == Type::LINEAR) { + writer.Add("LinearUnit"); + } else if (l_type == Type::ANGULAR) { + writer.Add("AngularUnit"); + } else if (l_type == Type::SCALE) { + writer.Add("ScaleUnit"); + } else if (l_type == Type::TIME) { + writer.Add("TimeUnit"); + } else if (l_type == Type::PARAMETRIC) { + writer.Add("ParametericUnit"); + } else { + writer.Add("Unit"); + } + + writer.AddObjKey("name"); + const auto &l_name = name(); + writer.Add(l_name); + + const auto &factor = conversionToSI(); + writer.AddObjKey("conversion_factor"); + writer.Add(factor, 15); + + const auto &l_codeSpace = codeSpace(); + if (!l_codeSpace.empty() && formatter->outputId()) { + writer.AddObjKey("id"); + PROJ::CPLJSonStreamingWriter::ObjectContext idContext(writer); + writer.AddObjKey("authority"); + writer.Add(l_codeSpace); + writer.AddObjKey("code"); + const auto &l_code = code(); + try { + writer.Add(std::stoi(l_code)); + } catch (const std::exception &) { + writer.Add(l_code); + } + } +} + //! @endcond // --------------------------------------------------------------------------- @@ -815,6 +863,23 @@ void IdentifiedObject::formatRemarks(WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +void IdentifiedObject::formatID(JSONFormatter *formatter) const { + const auto &ids(identifiers()); + auto &writer = formatter->writer(); + if (ids.size() == 1) { + writer.AddObjKey("id"); + ids.front()->_exportToJSON(formatter); + } else if (!ids.empty()) { + writer.AddObjKey("ids"); + PROJ::CPLJSonStreamingWriter::ArrayContext arrayContext(writer); + for (const auto &id : ids) { + id->_exportToJSON(formatter); + } + } +} + +// --------------------------------------------------------------------------- + bool IdentifiedObject::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index bf3092c1..6ba219d4 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -348,6 +348,41 @@ void PrimeMeridian::_exportToWKT( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void PrimeMeridian::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + PROJ::CPLJSonStreamingWriter::ObjectContext objectContext(writer); + + writer.AddObjKey("type"); + writer.Add("PrimeMeridian"); + + writer.AddObjKey("name"); + std::string l_name = + name()->description().has_value() ? nameStr() : "Greenwich"; + writer.Add(l_name); + + const auto &l_long = longitude(); + writer.AddObjKey("longitude"); + { + PROJ::CPLJSonStreamingWriter::ObjectContext longitudeContext(writer); + writer.AddObjKey("value"); + writer.Add(l_long.value(), 15); + + const auto &unit = l_long.unit(); + writer.AddObjKey("unit"); + unit._exportToJSON(formatter); + } + + if (formatter->outputId()) { + formatID(formatter); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress std::string PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) { const double valRad = angle.getSIValue(); diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 0db97d0b..0c9f8a0c 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -60,6 +60,7 @@ #include "proj_constants.h" +#include "proj_json_streaming_writer.hpp" #include "wkt1_parser.h" #include "wkt2_parser.h" @@ -8016,5 +8017,91 @@ PROJStringParser::createFromPROJString(const std::string &projString) { nullptr, nullptr, {}); } +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct JSONFormatter::Private { + PROJ::CPLJSonStreamingWriter writer_{nullptr, nullptr}; + DatabaseContextPtr dbContext_{}; + std::string result_{}; +}; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Constructs a new formatter. + * + * A formatter can be used only once (its internal state is mutated) + * + * @return new formatter. + */ +JSONFormatterNNPtr JSONFormatter::create( // cppcheck-suppress passedByValue + DatabaseContextPtr dbContext) { + auto ret = NN_NO_CHECK(JSONFormatter::make_unique<JSONFormatter>()); + ret->d->dbContext_ = dbContext; + return ret; +} + +// --------------------------------------------------------------------------- + +/** \brief Whether to use multi line output or not. */ +JSONFormatter &JSONFormatter::setMultiLine(bool multiLine) noexcept { + d->writer_.SetPrettyFormatting(multiLine); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set number of spaces for each indentation level (defaults to 4). + */ +JSONFormatter &JSONFormatter::setIndentationWidth(int width) noexcept { + d->writer_.SetIndentationSize(width); + return *this; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress + +JSONFormatter::JSONFormatter() : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +JSONFormatter::~JSONFormatter() = default; + +// --------------------------------------------------------------------------- + +PROJ::CPLJSonStreamingWriter &JSONFormatter::writer() const { + return d->writer_; +} + +// --------------------------------------------------------------------------- + +bool JSONFormatter::outputId() const { return true; } + +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Return the serialized JSON. + */ +const std::string &JSONFormatter::toString() const { + return d->writer_.GetString(); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +IJSONExportable::~IJSONExportable() = default; + +// --------------------------------------------------------------------------- + +std::string IJSONExportable::exportToJSON(JSONFormatter *formatter) const { + _exportToJSON(formatter); + return formatter->toString(); +} + +//! @endcond + } // namespace io NS_PROJ_END diff --git a/src/iso19111/metadata.cpp b/src/iso19111/metadata.cpp index 3725b072..761b909b 100644 --- a/src/iso19111/metadata.cpp +++ b/src/iso19111/metadata.cpp @@ -1088,6 +1088,26 @@ void Identifier::_exportToWKT(WKTFormatter *formatter) const { } } } + +// --------------------------------------------------------------------------- + +void Identifier::_exportToJSON(JSONFormatter *formatter) const { + const std::string &l_code = code(); + const std::string &l_codeSpace = *codeSpace(); + if (!l_codeSpace.empty() && !l_code.empty()) { + auto &writer = formatter->writer(); + PROJ::CPLJSonStreamingWriter::ObjectContext objContext(writer); + writer.AddObjKey("authority"); + writer.Add(l_codeSpace); + writer.AddObjKey("code"); + try { + writer.Add(std::stoi(l_code)); + } catch (const std::exception &) { + writer.Add(l_code); + } + } +} + //! @endcond // --------------------------------------------------------------------------- diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 5a0a8070..bad60324 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -285,6 +285,7 @@ set(SRC_LIBPROJ_CORE wkt_parser.cpp wkt_parser.hpp zpoly1.cpp + proj_json_streaming_writer.cpp ${CMAKE_CURRENT_BINARY_DIR}/proj_config.h ) @@ -293,6 +294,7 @@ set(HEADERS_LIBPROJ proj.h proj_experimental.h proj_constants.h + proj_json_streaming_writer.hpp geodesic.h ) diff --git a/src/proj_json_streaming_writer.cpp b/src/proj_json_streaming_writer.cpp new file mode 100644 index 00000000..3198308b --- /dev/null +++ b/src/proj_json_streaming_writer.cpp @@ -0,0 +1,297 @@ +/****************************************************************************** + * + * Project: CPL - Common Portability Library + * Purpose: JSon streaming writer + * Author: Even Rouault, even.rouault at spatialys.com + * + ****************************************************************************** + * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +/*! @cond Doxygen_Suppress */ + +#include <vector> +#include <string> + +#include "proj_json_streaming_writer.hpp" + +#include <string.h> +#include <sqlite3.h> +#include <stdarg.h> +#include <cmath> +#define CPLAssert(x) do {} while(0) +#define CPLIsNan std::isnan +#define CPLIsInf std::isinf +#define CPL_FRMT_GIB "%lld" +#define CPL_FRMT_GUIB "%llu" +typedef std::uint64_t GUIntBig; + +static std::string CPLSPrintf(const char* fmt, ...) +{ + std::string res; + res.resize(256); + va_list list; + va_start(list, fmt); + sqlite3_vsnprintf(256, &res[0], fmt, list); + va_end(list); + res.resize(strlen(&res[0])); + return res; +} + +namespace PROJ +{ + +CPLJSonStreamingWriter::CPLJSonStreamingWriter( + SerializationFuncType pfnSerializationFunc, + void* pUserData): + m_pfnSerializationFunc(pfnSerializationFunc), + m_pUserData(pUserData) +{} + +CPLJSonStreamingWriter::~CPLJSonStreamingWriter() +{ + CPLAssert( m_nLevel == 0 ); + CPLAssert( m_states.empty() ); +} + +void CPLJSonStreamingWriter::Print(const std::string& text) +{ + if( m_pfnSerializationFunc ) + { + m_pfnSerializationFunc(text.c_str(), m_pUserData); + } + else + { + m_osStr += text; + } +} + +void CPLJSonStreamingWriter::SetIndentationSize(int nSpaces) +{ + CPLAssert( m_nLevel == 0 ); + m_osIndent.clear(); + m_osIndent.resize(nSpaces, ' '); +} + +void CPLJSonStreamingWriter::IncIndent() +{ + m_nLevel ++; + if( m_bPretty ) + m_osIndentAcc += m_osIndent; +} + +void CPLJSonStreamingWriter::DecIndent() +{ + CPLAssert(m_nLevel > 0); + m_nLevel --; + if( m_bPretty ) + m_osIndentAcc.resize(m_osIndentAcc.size() - m_osIndent.size()); +} + +std::string CPLJSonStreamingWriter::FormatString(const std::string& str) +{ + std::string ret; + ret += '"'; + for( char ch: str ) + { + switch(ch) + { + case '"' : ret += "\\\""; break; + case '\\': ret += "\\\\"; break; + case '\b': ret += "\\b"; break; + case '\f': ret += "\\f"; break; + case '\n': ret += "\\n"; break; + case '\r': ret += "\\r"; break; + case '\t': ret += "\\t"; break; + default: + if( static_cast<unsigned char>(ch) < ' ' ) + ret += CPLSPrintf("\\u%04X", ch); + else + ret += ch; + break; + } + } + ret += '"'; + return ret; +} + +void CPLJSonStreamingWriter::EmitCommaIfNeeded() +{ + if( m_bWaitForValue ) + { + m_bWaitForValue = false; + } + else if( !m_states.empty() ) + { + if( !m_states.back().bFirstChild ) + { + Print(","); + if( m_bPretty && !m_bNewLineEnabled ) + Print(" "); + } + if( m_bPretty && m_bNewLineEnabled ) + { + Print("\n"); + Print(m_osIndentAcc); + } + m_states.back().bFirstChild = false; + } +} + +void CPLJSonStreamingWriter::StartObj() +{ + EmitCommaIfNeeded(); + Print("{"); + IncIndent(); + m_states.emplace_back(State(true)); +} + +void CPLJSonStreamingWriter::EndObj() +{ + CPLAssert(!m_bWaitForValue); + CPLAssert( !m_states.empty() ); + CPLAssert( m_states.back().bIsObj ); + DecIndent(); + if( !m_states.back().bFirstChild ) + { + if( m_bPretty && m_bNewLineEnabled ) + { + Print("\n"); + Print(m_osIndentAcc); + } + } + m_states.pop_back(); + Print("}"); +} + +void CPLJSonStreamingWriter::StartArray() +{ + EmitCommaIfNeeded(); + Print("["); + IncIndent(); + m_states.emplace_back(State(false)); +} + +void CPLJSonStreamingWriter::EndArray() +{ + CPLAssert( !m_states.empty() ); + CPLAssert( !m_states.back().bIsObj ); + DecIndent(); + if( !m_states.back().bFirstChild ) + { + if( m_bPretty && m_bNewLineEnabled ) + { + Print("\n"); + Print(m_osIndentAcc); + } + } + m_states.pop_back(); + Print("]"); +} + +void CPLJSonStreamingWriter::AddObjKey(const std::string& key) +{ + CPLAssert( !m_states.empty() ); + CPLAssert( m_states.back().bIsObj ); + CPLAssert(!m_bWaitForValue); + EmitCommaIfNeeded(); + Print(FormatString(key)); + Print(m_bPretty ? ": " : ":"); + m_bWaitForValue = true; +} + +void CPLJSonStreamingWriter::Add(bool bVal) +{ + EmitCommaIfNeeded(); + Print(bVal ? "true" : "false"); +} + +void CPLJSonStreamingWriter::Add(const std::string& str) +{ + EmitCommaIfNeeded(); + Print(FormatString(str)); +} + +void CPLJSonStreamingWriter::Add(const char* pszStr) +{ + EmitCommaIfNeeded(); + Print(FormatString(pszStr)); +} + +void CPLJSonStreamingWriter::Add(GIntBig nVal) +{ + EmitCommaIfNeeded(); + Print(CPLSPrintf(CPL_FRMT_GIB, nVal)); +} + +void CPLJSonStreamingWriter::Add(GUInt64 nVal) +{ + EmitCommaIfNeeded(); + Print(CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nVal))); +} + +void CPLJSonStreamingWriter::Add(float fVal, int nPrecision) +{ + EmitCommaIfNeeded(); + if( CPLIsNan(fVal) ) + { + Print("\"NaN\""); + } + else if( CPLIsInf(fVal) ) + { + Print( fVal > 0 ? "\"Infinity\"" : "\"-Infinity\"" ); + } + else + { + char szFormatting[10]; + snprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nPrecision); + Print(CPLSPrintf(szFormatting, fVal)); + } +} + +void CPLJSonStreamingWriter::Add(double dfVal, int nPrecision) +{ + EmitCommaIfNeeded(); + if( CPLIsNan(dfVal) ) + { + Print("\"NaN\""); + } + else if( CPLIsInf(dfVal) ) + { + Print( dfVal > 0 ? "\"Infinity\"" : "\"-Infinity\"" ); + } + else + { + char szFormatting[10]; + snprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nPrecision); + Print(CPLSPrintf(szFormatting, dfVal)); + } +} + +void CPLJSonStreamingWriter::AddNull() +{ + EmitCommaIfNeeded(); + Print("null"); +} + +} // namespace PROJ + +/*! @endcond */ diff --git a/src/proj_json_streaming_writer.hpp b/src/proj_json_streaming_writer.hpp new file mode 100644 index 00000000..d1510449 --- /dev/null +++ b/src/proj_json_streaming_writer.hpp @@ -0,0 +1,145 @@ +/****************************************************************************** + * + * Project: CPL - Common Portability Library + * Purpose: JSon streaming writer + * Author: Even Rouault, even.rouault at spatialys.com + * + ****************************************************************************** + * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef PROJ_JSON_STREAMING_WRITER_H +#define PROJ_JSON_STREAMING_WRITER_H + +/*! @cond Doxygen_Suppress */ + +#include <vector> +#include <string> + +#define CPL_DLL + +namespace PROJ +{ + +typedef std::int64_t GIntBig; +typedef std::uint64_t GUInt64; + +class CPL_DLL CPLJSonStreamingWriter +{ +public: + typedef void (*SerializationFuncType)(const char* pszTxt, void* pUserData); + +private: + CPLJSonStreamingWriter(const CPLJSonStreamingWriter&) = delete; + CPLJSonStreamingWriter& operator=(const CPLJSonStreamingWriter&) = delete; + + std::string m_osStr{}; + SerializationFuncType m_pfnSerializationFunc = nullptr; + void* m_pUserData = nullptr; + bool m_bPretty = true; + std::string m_osIndent = std::string(" "); + std::string m_osIndentAcc{}; + int m_nLevel = 0; + bool m_bNewLineEnabled = true; + struct State + { + bool bIsObj = false; + bool bFirstChild = true; + explicit State(bool bIsObjIn): bIsObj(bIsObjIn) {} + }; + std::vector<State> m_states{}; + bool m_bWaitForValue = false; + + void Print(const std::string& text); + void IncIndent(); + void DecIndent(); + static std::string FormatString(const std::string& str); + void EmitCommaIfNeeded(); + +public: + CPLJSonStreamingWriter(SerializationFuncType pfnSerializationFunc, + void* pUserData); + ~CPLJSonStreamingWriter(); + + void SetPrettyFormatting(bool bPretty) { m_bPretty = bPretty; } + void SetIndentationSize(int nSpaces); + + // cppcheck-suppress functionStatic + const std::string& GetString() const { return m_osStr; } + + void Add(const std::string& str); + void Add(const char* pszStr); + void Add(bool bVal); + void Add(int nVal) { Add(static_cast<GIntBig>(nVal)); } + void Add(unsigned int nVal) { Add(static_cast<GIntBig>(nVal)); } + void Add(GIntBig nVal); + void Add(GUInt64 nVal); + void Add(float fVal, int nPrecision = 9); + void Add(double dfVal, int nPrecision = 18); + void AddNull(); + + void StartObj(); + void EndObj(); + void AddObjKey(const std::string& key); + struct CPL_DLL ObjectContext + { + CPLJSonStreamingWriter& m_serializer; + explicit ObjectContext(CPLJSonStreamingWriter& serializer): + m_serializer(serializer) { m_serializer.StartObj(); } + ~ObjectContext() { m_serializer.EndObj(); } + }; + + void StartArray(); + void EndArray(); + struct CPL_DLL ArrayContext + { + CPLJSonStreamingWriter& m_serializer; + bool m_bForceSingleLine; + bool m_bNewLineEnabledBackup; + + ArrayContext(CPLJSonStreamingWriter& serializer, + bool bForceSingleLine = false): + m_serializer(serializer), + m_bForceSingleLine(bForceSingleLine), + m_bNewLineEnabledBackup(serializer.GetNewLine()) + { + if( m_bForceSingleLine ) + serializer.SetNewline(false); + m_serializer.StartArray(); + + } + ~ArrayContext() + { + m_serializer.EndArray(); + if( m_bForceSingleLine ) + m_serializer.SetNewline(m_bNewLineEnabledBackup); + } + }; + + bool GetNewLine() const { return m_bNewLineEnabled; } + void SetNewline(bool bEnabled) { m_bNewLineEnabled = bEnabled; } +}; + +} // namespace PROJ + +/*! @endcond */ + +#endif // PROJ_JSON_STREAMING_WRITER_H |
