Skip to content

Commit

Permalink
MiniJSONWriter: accept std::tuple<> #232
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Feb 29, 2024
1 parent 73cc5c7 commit 02cd31a
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 61 deletions.
15 changes: 9 additions & 6 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -876,12 +876,15 @@ class ConstraintKeeper final
void ExportConstraint(int i_con, const Container& cnt) {
if (GetLogger()) {
fmt::MemoryWriter wrt;
MiniJSONWriter<fmt::MemoryWriter> jw(wrt);
jw["con_type"] = cnt.con_.GetTypeName();
jw["index"] = i_con;
jw["depth"] = cnt.GetDepth();
// wrt.write("\"data\": ");
// WriteJSON(wrt, cnt.con_);
{
MiniJSONWriter jw(wrt);
jw["con_type"] = cnt.con_.GetTypeName();
jw["index"] = i_con;
jw["depth"] = cnt.GetDepth();
// wrt.write("\"data\": ");
// WriteJSON(wrt, cnt.con_);
}
wrt.write("\n"); // EOL
GetLogger()->Append(wrt);
}
}
Expand Down
35 changes: 20 additions & 15 deletions include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class FlatModel
assert(check_vars());
assert(!num_vars_orig_);
num_vars_orig_ = var_lb_.size();
ExportVars(var_type_.size()-1, lbs, ubs, types);
ExportVars(var_type_.size()-lbs.size(), lbs, ubs, types);
}

protected:
Expand All @@ -72,12 +72,14 @@ class FlatModel
for (int i=0;
GetFileAppender().IsOpen() && i<(int)lbs.size(); ++i) {
fmt::MemoryWriter wrt;
wrt.write("{} ", '{');
wrt.write("\"var_index\": {}, ", i+i_start);
wrt.write("\"bounds\": [{}, {}], ", lbs[i], ubs[i]);
wrt.write("\"type\": {}, ", (int)types[i]);
wrt.write("\"is_from_nl\": {}, ", (int)is_var_original(i));
wrt.write(" {}\n", '}'); // with EOL
{
MiniJSONWriter jw(wrt);
jw["var_index"] = i+i_start;
jw["bounds"] << lbs[i] << ubs[i];
jw["type"] = (int)types[i];
jw["is_from_nl"] = (int)is_var_original(i);
}
wrt.write("\n"); // with EOL
GetFileAppender().Append(wrt);
}
}
Expand Down Expand Up @@ -234,14 +236,17 @@ class FlatModel
void ExportObjective(int i_obj, const QuadraticObjective& obj) {
if (GetFileAppender().IsOpen()) {
fmt::MemoryWriter wrt;
wrt.write("{} ", '{');
wrt.write("\"obj_index\": {}, ", i_obj);
wrt.write("\"sense\": {}, ", obj.obj_sense());
wrt.write("\"qp_terms\": ");
WriteJSON(wrt, obj.GetQPTerms());
wrt.write("\"lin_terms\": ");
WriteJSON(wrt, obj.GetLinTerms());
wrt.write(" {}\n", '}'); // with EOL
{
MiniJSONWriter jw(wrt);
jw["obj_index"] = i_obj;
jw["sense"] = (int)obj.obj_sense();
wrt.write("\"qp_terms\": ");
WriteJSON(wrt, obj.GetQPTerms());
wrt.write("\"lin_terms\": ");
WriteJSON(wrt, obj.GetLinTerms());
wrt.write(" {}\n", '}'); // with EOL
}
wrt.write("\n"); // EOL
GetFileAppender().Append(wrt);
}
}
Expand Down
58 changes: 44 additions & 14 deletions include/mp/util-json-write.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <vector>
#include <string>
#include <tuple>
#include <type_traits>

namespace mp {
Expand Down Expand Up @@ -57,37 +58,44 @@ class MiniJSONWriter {
/// operator[]: make/ensure *this a dictionary,
/// add and return a new element at \a key.
/// Allows the syntax `node[key] = val;`,
/// or `node[key] << val1 << val2 ...;`,
/// but also writing a complex subtree manually.
Node operator[](const char* key);
Node operator[](std::string_view key);

/// operator<<: make/ensure *this an array
/// and write \a val a new element.
///
/// @param val: scalar or container.
/// @param val: scalar, tuple or container.
/// For non-supported types, define global method
/// Serialize(MiniJSONWriter&, const YourType& ).
/// Serialize(MiniJSONWriter& , const YourType& ).
///
/// @return *this.
template <class Value>
Node& operator<<(const Value& val)
{ EnsureArray(); Write(val); return *this; }
Node& operator<<(const Value& val) {
EnsureArray();
InsertElementSeparator();
Write(val);
return *this;
}

/// operator=: write \a val as a whole.
///
/// @param val: scalar or container.
/// @param val: scalar, tuple or container.
/// For non-supported types, define global method
/// Serialize(MiniJSONWrt& , const YourType& ).
/// Serialize(MiniJSONWriter& , const YourType& ).
///
/// @note Can be called only once on a single node.
template <class Value>
void operator=(const Value& val)
{ EnsureUnset(); Write(val); Close(); }

/// Write a sequence between two iterators
/// @return *this
template <class It>
void WriteSequence(It b, It e) {
Node& WriteSequence(It b, It e) {
for ( ; b!=e; ++b)
(*this) << (*b);
return *this;
}

/// Close node.
Expand Down Expand Up @@ -117,8 +125,8 @@ class MiniJSONWriter {

/// Make sure this node has not been written into.
void EnsureUnset();
/// Make sure this is a scalar node.
void EnsureScalar();
/// If unset, mark scalar node.
void MakeScalarIfUnset();
/// Make sure this is an array node.
void EnsureArray();
/// Make sure this is a dictionary node.
Expand All @@ -138,8 +146,8 @@ class MiniJSONWriter {
/// Insert element separator if needed
void InsertElementSeparator();

void DoWrite(const char* s) { DoWriteScalar(s); }
void DoWrite(const std::string& s) { DoWriteScalar(s); }
void DoWrite(const char* s) { DoWriteString(s); }
void DoWrite(const std::string& s) { DoWriteString(s); }

template <typename Arithmetic,
typename
Expand All @@ -152,9 +160,31 @@ class MiniJSONWriter {
decltype(*begin(std::declval<C>()))> >
void DoWrite(const C& c) { WriteSequence(c.begin(), c.end()); }

/// https://www.cppstories.com/2022/tuple-iteration-apply/
template <typename... Arg>
void DoWrite(const std::tuple<Arg...>& tup) {
std::apply([this](const auto&... tupleArgs) {
auto printElem = [this](const auto& x) {
(*this) << x;
};
(printElem(tupleArgs), ...);
}, tup
);
}

template <class Value>
void DoWriteScalar(const Value& val)
{ EnsureScalar(); wrt_.write("{}", val); }
void DoWriteScalar(const Value& val) {
MakeScalarIfUnset();
wrt_.write("{}", val);
++n_written_;
}

template <class Str>
void DoWriteString(const Str& val) {
MakeScalarIfUnset();
wrt_.write("\"{}\"", val);
++n_written_;
}

private:
Formatter& wrt_;
Expand Down
18 changes: 12 additions & 6 deletions include/mp/util-json-write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#include <cassert>

#include "mp/format.h"

#include "mp/util-json-write.h"

namespace mp {
Expand All @@ -34,15 +36,19 @@ typename MiniJSONWriter<StringWriter>::Node
MiniJSONWriter<StringWriter>::operator++() {
EnsureArray();
InsertElementSeparator();
++n_written_;
return Node{*this};
}

template <class StringWriter>
typename MiniJSONWriter<StringWriter>::Node
MiniJSONWriter<StringWriter>::operator[](const char* key) {
MiniJSONWriter<StringWriter>::operator[](std::string_view key) {
EnsureDictionary();
InsertElementSeparator();
wrt_.write("{}: ", key);
wrt_.write("\"{}\": ", // Need StringRef until newer {fmt}
fmt::StringRef(key.data(), key.size())
);
++n_written_;
return Node{*this};
}

Expand All @@ -52,9 +58,10 @@ void MiniJSONWriter<StringWriter>::EnsureUnset() {
}

template <class StringWriter>
void MiniJSONWriter<StringWriter>::EnsureScalar() {
EnsureUnset();
kind_ = Kind::Scalar;
void MiniJSONWriter<StringWriter>::MakeScalarIfUnset() {
if (Kind::Unset == kind_) {
kind_ = Kind::Scalar;
}
}

template <class StringWriter>
Expand All @@ -81,7 +88,6 @@ template <class StringWriter>
void MiniJSONWriter<StringWriter>::EnsureCanWrite() {
switch (kind_) {
case Kind::Unset:
assert(false && "unset MiniJSONWriter node kind for writing");
break;
case Kind::Scalar:
assert(0==n_written_);
Expand Down
36 changes: 16 additions & 20 deletions include/mp/valcvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <functional>

#include "mp/utils-string.h"
#include "mp/util-json-write.hpp"

#include "valcvt-node.h"
#include "valcvt-link.h"
Expand Down Expand Up @@ -187,36 +188,31 @@ class ValuePresolverImpl : public BasicValuePresolver {
if (GetExport()) {
ln.ExportEntryItems(entry_items_, i_entry);
fmt::MemoryWriter wrt;
wrt.write("{} ", '{');
wrt.write("\"link_index\": [{}, {}], ", i_exported_, i_entry);
wrt.write("\"link_type\": \"{}\", ", ln.GetTypeName());
wrt.write("\"source_nodes\": [");
WriteNodes(wrt, entry_items_.src_items_);
wrt.write(" ], "); // end source nodes
wrt.write("\"dest_nodes\": [ ");
WriteNodes(wrt, entry_items_.dest_items_);
wrt.write(" ]"); // end dest nodes
wrt.write(" {}\n", '}'); // with EOL
{
MiniJSONWriter jw(wrt);
jw["link_index"] = std::make_tuple(i_exported_, i_entry);
jw["link_type"] = ln.GetTypeName();
WriteNodes(jw["source_nodes"], entry_items_.src_items_);
WriteNodes(jw["dest_nodes"], entry_items_.dest_items_);
}
/// Export record
wrt.write("\n"); // EOL
bts_.Append(wrt);
}
}

/// Write a vector of nodes
void WriteNodes(fmt::MemoryWriter& wrt, const std::vector<NodeRange>& nodes) {
template <class JSON>
void WriteNodes(JSON jw, const std::vector<NodeRange>& nodes) {
for (size_t i=0; i<nodes.size(); ++i) {
const auto& nd = nodes[i];
auto jelement = ++jw; // We write an array
if (nd.IsSingleIndex())
wrt.write("{} \"{}\": {} {}",
'{', nd.GetValueNode()->GetName(), (int)nd, '}');
jelement[nd.GetValueNode()->GetName()] = (int)nd;
else
wrt.write("{} \"{}\": [{}, {}] {}",
'{', nd.GetValueNode()->GetName(),
nd.GetIndexRange().beg_,
nd.GetIndexRange().end_-1, // print the exact last value
'}');
if (i != nodes.size()-1)
wrt.write(",");
jelement[nd.GetValueNode()->GetName()]
<< nd.GetIndexRange().beg_
<< (nd.GetIndexRange().end_-1); // print the exact last value
}
}

Expand Down

0 comments on commit 02cd31a

Please sign in to comment.