dynamic dynamic::merge_diff(const dynamic& source, const dynamic& target) { if (!source.isObject() || source.type() != target.type()) { return target; } dynamic diff = object; // added/modified keys for (const auto& pair : target.items()) { auto it = source.find(pair.first); if (it == source.items().end()) { diff[pair.first] = pair.second; } else { diff[pair.first] = merge_diff(source[pair.first], target[pair.first]); } } // removed keys for (const auto& pair : source.items()) { auto it = target.find(pair.first); if (it == target.items().end()) { diff[pair.first] = nullptr; } } return diff; }
static void bserEncode(dynamic const& dyn, QueueAppender& appender, const serialization_opts& opts) { switch (dyn.type()) { case dynamic::Type::NULLT: appender.write((int8_t)BserType::Null); return; case dynamic::Type::BOOL: appender.write( (int8_t)(dyn.getBool() ? BserType::True : BserType::False)); return; case dynamic::Type::DOUBLE: { double dval = dyn.getDouble(); appender.write((int8_t)BserType::Real); appender.write(dval); return; } case dynamic::Type::INT64: bserEncodeInt(dyn.getInt(), appender); return; case dynamic::Type::OBJECT: bserEncodeObject(dyn, appender, opts); return; case dynamic::Type::ARRAY: bserEncodeArray(dyn, appender, opts); return; case dynamic::Type::STRING: bserEncodeString(dyn.getString(), appender); return; } }
Optional<SchemaError> validate(ValidationContext&, const dynamic& value) const override { auto it = std::find(allowedTypes_.begin(), allowedTypes_.end(), value.type()); if (it == allowedTypes_.end()) { return makeError("a value of type ", typeStr_, value); } return none; }
CrontabSelector::CrontabSelector( const dynamic &d, int64_t min_val, int64_t max_val, function<int64_t(const string& lc_str)> str_to_value ) : start_(min_val), end_(max_val), period_(1), minVal_(min_val), maxVal_(max_val) { switch (d.type()) { case dynamic::Type::INT64: case dynamic::Type::STRING: sortedValues_.emplace_back(parseValue(d, str_to_value)); break; case dynamic::Type::ARRAY: for (const auto& val : d) { sortedValues_.emplace_back(parseValue(val, str_to_value)); } // If somebody specifies [] for a selector, we have to silently // accept it, since PHP's JSON library can morph {} into [], and {} // must mean "default selector accepting all values." break; case dynamic::Type::OBJECT: for (const auto& pair : d.items()) { // Interval is first so that it doesn't accept strings like "jan" if (pair.first == "period") { period_ = pair.second.asInt(); if (period_ < 1 || period_ >= maxVal_ - minVal_) { throw runtime_error(format( "period not in [1, {}]: {}", maxVal_ - minVal_, period_ ).str()); } continue; } // For start & end, we are happy to accept string names auto val = parseValue(pair.second, str_to_value); if (pair.first == "start") { start_ = val; } else if (pair.first == "end") { end_ = val; } else { throw runtime_error(format("Unknown key: {}", pair.first).str()); } } // If we got an empty object, no problem -- this selector will // follow the default of "match everything". break; default: throw runtime_error(format( "Bad type for crontab selector: {}", d.typeName() ).str()); } sort(sortedValues_.begin(), sortedValues_.end()); }
Optional<SchemaError> validate(ValidationContext&, const dynamic& value) const override { if (length_ < 0) { return none; } if (value.type() != type_) { return none; } if (!Comparison()(length_, value.size())) { return makeError("different length string/array/object", value); } return none; }
bool dynamic::operator==(dynamic const& o) const { if (type() != o.type()) { if (isNumber() && o.isNumber()) { auto& integ = isInt() ? *this : o; auto& doubl = isInt() ? o : *this; return integ.asInt() == doubl.asDouble(); } return false; } #define FB_X(T) return *getAddress<T>() == *o.getAddress<T>(); FB_DYNAMIC_APPLY(type_, FB_X); #undef FB_X }
static void GenStat(Stat& stat, const dynamic& v) { switch (v.type()) { case dynamic::ARRAY: { for (auto &i : v) GenStat(stat, i); stat.arrayCount++; stat.elementCount += v.size(); } break; case dynamic::OBJECT: { auto p = v.items(); for (auto& i : p) { GenStat(stat, i.second); stat.stringLength += i.first.size(); } stat.objectCount++; stat.memberCount += v.size(); stat.stringCount += v.size(); } break; case dynamic::STRING: stat.stringCount++; stat.stringLength += v.size(); break; case dynamic::INT64: case dynamic::DOUBLE: stat.numberCount++; break; case dynamic::BOOL: if (v.getBool()) stat.trueCount++; else stat.falseCount++; break; case dynamic::NULLT: stat.nullCount++; break; } }