option for deterministic descriptions of sets & tables

This commit is contained in:
Vern Paxson 2021-03-18 16:18:32 -07:00
parent a808e166a4
commit 9e4c87b112
3 changed files with 51 additions and 12 deletions

View file

@ -40,6 +40,7 @@ ODesc::ODesc(DescType t, File* arg_f)
indent_level = 0;
is_short = false;
want_quotes = false;
want_determinism = false;
do_flush = true;
include_stats = false;
indent_with_spaces = 0;

View file

@ -47,6 +47,11 @@ public:
bool WantQuotes() const { return want_quotes; }
void SetQuotes(bool q) { want_quotes = q; }
// Whether to ensure deterministic output (for example, when
// describing TableVal's).
bool WantDeterminism() const { return want_determinism; }
void SetDeterminism(bool d) { want_determinism = d; }
// Whether we want to print statistics like access time and execution
// count where available.
bool IncludeStats() const { return include_stats; }
@ -122,7 +127,7 @@ public:
Add("\n", 0);
}
// Bypasses the escaping enabled via SetEscape().
// Bypasses the escaping enabled via EnableEscaping().
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
void AddRaw(const std::string &s) { AddBytesRaw(s.data(), s.size()); }
@ -194,6 +199,7 @@ protected:
bool escape; // escape unprintable characters in output?
bool is_short;
bool want_quotes;
bool want_determinism;
int indent_with_spaces;

View file

@ -2334,6 +2334,9 @@ void TableVal::Describe(ODesc* d) const
d->PushIndent();
}
bool determ = d->WantDeterminism();
std::vector<std::string> elem_descs;
auto iter = table_val->begin();
for ( int i = 0; i < n; ++i )
@ -2347,7 +2350,10 @@ void TableVal::Describe(ODesc* d) const
auto vl = table_hash->RecoverVals(*k);
int dim = vl->Length();
if ( i > 0 )
ODesc intermediary_d;
ODesc* d_ptr = determ ? &intermediary_d : d;
if ( ! determ && i > 0 )
{
if ( ! d->IsBinary() )
d->Add(",");
@ -2358,42 +2364,67 @@ void TableVal::Describe(ODesc* d) const
if ( d->IsReadable() )
{
if ( dim != 1 || ! table_type->IsSet() )
d->Add("[");
d_ptr->Add("[");
}
else
{
d->Add(dim);
d->SP();
d_ptr->Add(dim);
d_ptr->SP();
}
vl->Describe(d);
vl->Describe(d_ptr);
if ( table_type->IsSet() )
{ // We're a set, not a table.
if ( d->IsReadable() )
if ( dim != 1 )
d->AddSP("]");
d_ptr->AddSP("]");
}
else
{
if ( d->IsReadable() )
d->AddSP("] =");
d_ptr->AddSP("] =");
if ( v->GetVal() )
v->GetVal()->Describe(d);
v->GetVal()->Describe(d_ptr);
}
if ( d->IsReadable() && ! d->IsShort() && d->IncludeStats() )
{
d->Add(" @");
d->Add(util::detail::fmt_access_time(v->ExpireAccessTime()));
d_ptr->Add(" @");
d_ptr->Add(util::detail::fmt_access_time(v->ExpireAccessTime()));
}
if ( determ )
elem_descs.emplace_back(d_ptr->Description());
++iter;
}
if ( iter != table_val->end() )
reporter->InternalError("hash table overflow in TableVal::Describe");
if ( determ )
{
sort(elem_descs.begin(), elem_descs.end());
iter = table_val->begin();
bool did_elems = false;
for ( const auto& ed : elem_descs )
{
if ( did_elems )
{
if ( ! d->IsBinary() )
d->Add(",");
d->NL();
}
d->Add(ed);
did_elems = true;
}
}
if ( d->IsPortable() || d->IsReadable() )
{
d->PopIndent();
@ -3501,7 +3532,8 @@ void describe_vals(const std::vector<ValPtr>& vals,
if ( i > offset && d->IsReadable() && d->Style() != RAW_STYLE )
d->Add(", ");
vals[i]->Describe(d);
if ( vals[i] )
vals[i]->Describe(d);
}
}