mirror of
https://github.com/NixOS/nix
synced 2025-06-27 08:31:16 +02:00
197 lines
5.3 KiB
C++
197 lines
5.3 KiB
C++
#include "attr-set.hh"
|
|
#include "config.hh"
|
|
#include "eval.hh"
|
|
#include "gc/gc.h"
|
|
#include "globals.hh"
|
|
#include "value.hh"
|
|
|
|
#include "nix_api_expr.h"
|
|
#include "nix_api_expr_internal.h"
|
|
#include "nix_api_external.h"
|
|
#include "nix_api_util.h"
|
|
#include "nix_api_util_internal.h"
|
|
#include "nix_api_value.h"
|
|
#include "value/context.hh"
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#ifdef HAVE_BOEHMGC
|
|
#define GC_INCLUDE_NEW 1
|
|
#include "gc_cpp.h"
|
|
#endif
|
|
|
|
struct nix_string_return {
|
|
std::string str;
|
|
};
|
|
|
|
struct nix_printer {
|
|
std::ostream &s;
|
|
};
|
|
|
|
struct nix_string_context {
|
|
nix::NixStringContext &ctx;
|
|
};
|
|
|
|
void nix_set_string_return(nix_string_return *str, const char *c) {
|
|
str->str = c;
|
|
}
|
|
|
|
nix_err nix_external_print(nix_c_context *context, nix_printer *printer,
|
|
const char *c) {
|
|
if (context)
|
|
context->last_err_code = NIX_OK;
|
|
try {
|
|
printer->s << c;
|
|
}
|
|
NIXC_CATCH_ERRS
|
|
}
|
|
|
|
nix_err nix_external_add_string_context(nix_c_context *context,
|
|
nix_string_context *ctx,
|
|
const char *c) {
|
|
if (context)
|
|
context->last_err_code = NIX_OK;
|
|
try {
|
|
auto r = nix::NixStringContextElem::parse(c);
|
|
ctx->ctx.insert(r);
|
|
}
|
|
NIXC_CATCH_ERRS
|
|
}
|
|
|
|
class NixCExternalValue : public nix::ExternalValueBase {
|
|
NixCExternalValueDesc &desc;
|
|
void *v;
|
|
|
|
public:
|
|
NixCExternalValue(NixCExternalValueDesc &desc, void *v) : desc(desc), v(v){};
|
|
void *get_ptr() { return v; }
|
|
/**
|
|
* Print out the value
|
|
*/
|
|
virtual std::ostream &print(std::ostream &str) const override {
|
|
nix_printer p{str};
|
|
desc.print(v, &p);
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* Return a simple string describing the type
|
|
*/
|
|
virtual std::string showType() const override {
|
|
nix_string_return res;
|
|
desc.showType(v, &res);
|
|
return std::move(res.str);
|
|
}
|
|
|
|
/**
|
|
* Return a string to be used in builtins.typeOf
|
|
*/
|
|
virtual std::string typeOf() const override {
|
|
nix_string_return res;
|
|
desc.typeOf(v, &res);
|
|
return std::move(res.str);
|
|
}
|
|
|
|
/**
|
|
* Coerce the value to a string.
|
|
*/
|
|
virtual std::string coerceToString(const nix::Pos &pos,
|
|
nix::NixStringContext &context,
|
|
bool copyMore,
|
|
bool copyToStore) const override {
|
|
if (!desc.coerceToString) {
|
|
return nix::ExternalValueBase::coerceToString(pos, context, copyMore,
|
|
copyToStore);
|
|
}
|
|
nix_string_context ctx{context};
|
|
nix_string_return res{""};
|
|
// todo: pos, errors
|
|
desc.coerceToString(v, &ctx, copyMore, copyToStore, &res);
|
|
if (res.str.empty()) {
|
|
return nix::ExternalValueBase::coerceToString(pos, context, copyMore,
|
|
copyToStore);
|
|
}
|
|
return std::move(res.str);
|
|
}
|
|
|
|
/**
|
|
* Compare to another value of the same type.
|
|
*/
|
|
virtual bool operator==(const ExternalValueBase &b) const override {
|
|
if (!desc.equal) {
|
|
return false;
|
|
}
|
|
auto r = dynamic_cast<const NixCExternalValue *>(&b);
|
|
if (!r)
|
|
return false;
|
|
return desc.equal(v, r->v);
|
|
}
|
|
|
|
/**
|
|
* Print the value as JSON.
|
|
*/
|
|
virtual nlohmann::json
|
|
printValueAsJSON(nix::EvalState &state, bool strict,
|
|
nix::NixStringContext &context,
|
|
bool copyToStore = true) const override {
|
|
if (!desc.printValueAsJSON) {
|
|
return nix::ExternalValueBase::printValueAsJSON(state, strict, context,
|
|
copyToStore);
|
|
}
|
|
nix_string_context ctx{context};
|
|
nix_string_return res{""};
|
|
desc.printValueAsJSON(v, (State *)&state, strict, &ctx, copyToStore, &res);
|
|
if (res.str.empty()) {
|
|
return nix::ExternalValueBase::printValueAsJSON(state, strict, context,
|
|
copyToStore);
|
|
}
|
|
return nlohmann::json::parse(res.str);
|
|
}
|
|
|
|
/**
|
|
* Print the value as XML.
|
|
*/
|
|
virtual void printValueAsXML(nix::EvalState &state, bool strict,
|
|
bool location, nix::XMLWriter &doc,
|
|
nix::NixStringContext &context,
|
|
nix::PathSet &drvsSeen,
|
|
const nix::PosIdx pos) const override {
|
|
if (!desc.printValueAsXML) {
|
|
return nix::ExternalValueBase::printValueAsXML(
|
|
state, strict, location, doc, context, drvsSeen, pos);
|
|
}
|
|
nix_string_context ctx{context};
|
|
desc.printValueAsXML(v, (State *)&state, strict, location, &doc, &ctx,
|
|
&drvsSeen, *reinterpret_cast<const uint32_t *>(&pos));
|
|
}
|
|
|
|
virtual ~NixCExternalValue() override{};
|
|
};
|
|
|
|
ExternalValue *nix_create_external_value(nix_c_context *context,
|
|
NixCExternalValueDesc *desc, void *v) {
|
|
if (context)
|
|
context->last_err_code = NIX_OK;
|
|
try {
|
|
auto ret = new
|
|
#ifdef HAVE_BOEHMGC
|
|
(GC)
|
|
#endif
|
|
NixCExternalValue(*desc, v);
|
|
nix_gc_incref(nullptr, ret);
|
|
return (ExternalValue *)ret;
|
|
}
|
|
NIXC_CATCH_ERRS_NULL
|
|
}
|
|
|
|
void *nix_get_external_value_content(nix_c_context *context, ExternalValue *b) {
|
|
if (context)
|
|
context->last_err_code = NIX_OK;
|
|
try {
|
|
auto r = dynamic_cast<NixCExternalValue *>((nix::ExternalValueBase *)b);
|
|
if (r)
|
|
return r->get_ptr();
|
|
return nullptr;
|
|
}
|
|
NIXC_CATCH_ERRS_NULL
|
|
}
|