1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 08:31:16 +02:00
nix/src/libexpr/c/nix_api_external.cc
2024-03-28 10:46:39 +01:00

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
}