#pragma once #include #include #include #include #include #include #include #include namespace Preserves { template class Atomic: public ValueImpl { protected: Atom value; public: Atomic(Atom const& value) : value(value) {} Atom& _value() { return value; } Atom const& _value() const { return value; } ValueKind value_kind() const { return kind; } }; #define PRESERVES_ATOMIC_VALUE_CLASS(Name, a_t, r_t, VK, getter, extra) \ template \ class Name: public Atomic { \ public: \ Name(a_t const& value) : Atomic(value) {} \ boost::optional getter() const override { return this->value; } \ extra \ } PRESERVES_ATOMIC_VALUE_CLASS(Boolean, bool, bool, ValueKind::Boolean, as_bool, BinaryWriter& write(BinaryWriter& w) const override { return w << this->_value(); }); PRESERVES_ATOMIC_VALUE_CLASS(Double, double, double, ValueKind::Double, as_double, BinaryWriter& write(BinaryWriter& w) const override { return w << this->_value(); }); PRESERVES_ATOMIC_VALUE_CLASS(Uint64, uint64_t, uint64_t, ValueKind::SignedInteger, as_unsigned, BinaryWriter& write(BinaryWriter& w) const override { return w << this->_value(); } boost::optional as_signed() const override { if (this->value <= uint64_t(std::numeric_limits::max())) { return this->value; } else { return boost::none; } } boost::optional as_double() const override { if (uint64_t(double(this->value)) == this->value) { return double(this->value); } else { return boost::none; } }); PRESERVES_ATOMIC_VALUE_CLASS(Int64, int64_t, int64_t, ValueKind::SignedInteger, as_signed, BinaryWriter& write(BinaryWriter& w) const override { return w << this->_value(); } boost::optional as_unsigned() const override { if (this->value >= 0) { return this->value; } else { return boost::none; } } boost::optional as_double() const override { if (int64_t(double(this->value)) == this->value) { return double(this->value); } else { return boost::none; } }); PRESERVES_ATOMIC_VALUE_CLASS(BigNum, std::vector, std::vector const&, ValueKind::SignedInteger, as_bignum, BinaryWriter& write(BinaryWriter& w) const override { return w.bignum(this->_value()); }); PRESERVES_ATOMIC_VALUE_CLASS(String, std::string, std::string const&, ValueKind::String, as_string, BinaryWriter& write(BinaryWriter& w) const override { return w.string(this->_value()); }); PRESERVES_ATOMIC_VALUE_CLASS(ByteString, std::vector, std::vector const&, ValueKind::ByteString, as_bytes, BinaryWriter& write(BinaryWriter& w) const override { return w.bytes(this->_value()); }); PRESERVES_ATOMIC_VALUE_CLASS(Symbol, std::string, std::string const&, ValueKind::Symbol, as_symbol, BinaryWriter& write(BinaryWriter& w) const override { return w.symbol(this->_value()); }); template class Record: public ValueImpl { public: Value labelValue; std::vector> fields; Record(Value const& label) : labelValue(label), fields() {} Record(Value const& label, std::vector> const& fields) : labelValue(label), fields(fields) {} ValueKind value_kind() const { return ValueKind::Record; } boost::optional> label() const override { return labelValue; } size_t size() const { return fields.size(); } boost::optional> get(size_t index) const { if (index < size()) { return fields[index]; } else { return boost::none; } } bool add(Value const& value) override { fields.push_back(value); return true; } bool set(size_t index, Value const& value) override { if (index < size()) { fields[index] = value; } return false; } bool operator<(Record const& other) const { if (labelValue < other.labelValue) return true; if (other.labelValue < labelValue) return false; return fields < other.fields; } BinaryWriter& write(BinaryWriter& w) const override { return w.record(labelValue, fields); } }; template class Sequence: public ValueImpl { public: std::vector> values; Sequence() : values() {} Sequence(std::vector> const& values) : values(values) {} ValueKind value_kind() const { return ValueKind::Sequence; } boost::optional> const&> as_sequence() const override { return values; } size_t size() const override { return values.size(); } boost::optional> get(size_t index) const override { if (index < size()) { return values[index]; } else { return boost::none; } } bool add(Value const& value) override { values.push_back(value); return true; } bool set(size_t index, Value const& value) override { if (index < size()) { values[index] = value; } return false; } BinaryWriter& write(BinaryWriter& w) const override { return w.sequence(values); } }; template class Set: public ValueImpl { public: std::set> values; Set() : values() {} Set(std::set> const& values) : values(values) {} ValueKind value_kind() const { return ValueKind::Set; } boost::optional> const&> as_set() const override { return values; } size_t size() const override { return values.size(); } bool contains(Value const& key) const override { return values.count(key) > 0; } bool add(Value const& value) override { return values.insert(value).second; } bool erase(Value const& value) override { return values.erase(value) > 0; } BinaryWriter& write(BinaryWriter& w) const override { return w.set(values); } }; template class Dictionary: public ValueImpl { public: std::map, Value> values; Dictionary() : values() {} Dictionary(std::map, Value> const& values) : values(values) {} ValueKind value_kind() const { return ValueKind::Dictionary; } boost::optional, Value> const&> as_dictionary() const override { return values; } size_t size() const override { return values.size(); } bool contains(Value const& key) const override { return values.count(key) > 0; } boost::optional> get(Value const& key) const override { auto i = values.find(key); if (i == values.end()) return boost::none; return i->second; } bool set(Value const& key, Value const& value) override { return values.emplace(key, value).second; } bool erase(Value const& key) override { return values.erase(key) > 0; } BinaryWriter& write(BinaryWriter& w) const override { return w.dictionary(values); } }; template class Embedded: public ValueImpl { public: std::shared_ptr value; Embedded(std::shared_ptr const& value) : value(value) {} ValueKind value_kind() const { return ValueKind::Embedded; } boost::optional> as_embedded() const override { return value; } BinaryWriter& write(BinaryWriter& w) const override { w << BinaryTag::Embedded; return value->write(w); } }; class GenericEmbedded: public Value { public: GenericEmbedded(std::shared_ptr> p) : Value(p) {} static std::shared_ptr wrap(Value<> v) { return std::make_shared(v._impl()); } BinaryWriter& write(BinaryWriter& w) const { return (*this)->write(w); } }; template class AnnotatedValue: public ValueImpl { std::vector> anns; Value underlying; friend class ValueImpl; protected: Value internal_annotate(std::shared_ptr> const& self, Value const &ann) { if (self.use_count() == 1) { anns.push_back(ann); return self; } else { auto a = std::make_shared>(std::vector>(anns), underlying); a->anns.push_back(ann); return Value(a); } } public: AnnotatedValue(std::vector> &&anns, Value const& v) : anns(anns), underlying(v) {} ValueKind value_kind() const override { return underlying.value_kind(); } bool is_mutable() const override { return underlying.is_mutable(); } boost::optional as_bool() const override { return underlying.as_bool(); } boost::optional as_double() const override { return underlying.as_double(); } boost::optional as_unsigned() const override { return underlying.as_unsigned(); } boost::optional as_signed() const override { return underlying.as_signed(); } boost::optional const&> as_bignum() const override { return underlying.as_bignum(); } boost::optional as_string() const override { return underlying.as_string(); } boost::optional const&> as_bytes() const override { return underlying.as_bytes(); } boost::optional as_symbol() const override { return underlying.as_symbol(); } boost::optional const&> as_record() const override { return underlying.as_record(); } boost::optional> const&> as_sequence() const override { return underlying.as_sequence(); } boost::optional> const&> as_set() const override { return underlying.as_set(); } boost::optional,Value> const&> as_dictionary() const override { return underlying.as_dictionary(); } boost::optional> as_embedded() const override { return underlying.as_embedded(); } boost::optional> label() const override { return underlying.label(); } size_t size() const override { return underlying.size(); } bool contains(Value const& key) const override { return underlying.contains(key); } boost::optional> get(Value const& key) const override { return underlying.get(key); } boost::optional> get(size_t index) const override { return underlying.get(index); } bool add(Value const& item) override { return underlying->add(item); } bool set(Value const& key, Value const& value) override { return underlying->set(key, value); } bool set(size_t index, Value const& value) override { return underlying->set(index, value); } bool erase(Value const& key) override { return underlying->erase(key); } boost::optional> const&> annotations() const override { return anns; } BinaryWriter& write(BinaryWriter &w) const override { return w.annotated(underlying, anns); } }; template Value Value::annotate(Value const& ann) const { return p->internal_annotate(p, ann); } template Value ValueImpl::internal_annotate(std::shared_ptr> const& self, Value const &ann) { auto a = std::make_shared>(std::vector>(), Value(self)); a->anns.push_back(ann); return Value(a); } template Value Value::from_bool(bool b) { return Value(new Boolean(b)); } template Value Value::from_double(double d) { return Value(new Double(d)); } template Value Value::from_int(uint64_t i) { return Value(new Uint64(i)); } template Value Value::from_int(int64_t i) { return Value(new Int64(i)); } template Value Value::from_string(std::string const& s) { return Value(new String(s)); } template Value Value::sequence(std::vector> const& values) { return Value(new Sequence(values)); } template Value Value::from_embedded(std::shared_ptr const& v) { return Value(new Embedded(v)); } }