1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 21:01:16 +02:00

libexpr: add C bindings

This commit is contained in:
Yorick van Pelt 2023-07-14 15:53:30 +02:00 committed by José Luis Lafuente
parent 1d41600498
commit e76652a5d3
No known key found for this signature in database
GPG key ID: 8A3455EBE455489A
10 changed files with 1527 additions and 1 deletions

View file

@ -0,0 +1,198 @@
#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_returned_string {
std::string str;
};
struct nix_printer {
std::ostream &s;
};
struct nix_string_context {
nix::NixStringContext &ctx;
};
nix_returned_string *nix_external_alloc_string(const char *c) {
return new nix_returned_string{c};
}
void nix_external_dealloc_string(nix_returned_string *str) { delete str; }
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 {
std::unique_ptr<nix_returned_string> r(desc.showType(v));
return std::move(r->str);
}
/**
* Return a string to be used in builtins.typeOf
*/
virtual std::string typeOf() const override {
std::unique_ptr<nix_returned_string> r(desc.typeOf(v));
return std::move(r->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};
// todo: pos, errors
std::unique_ptr<nix_returned_string> r(
desc.coerceToString(v, &ctx, copyMore, copyToStore));
if (!r) {
return nix::ExternalValueBase::coerceToString(pos, context, copyMore,
copyToStore);
}
return std::move(r->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};
std::unique_ptr<nix_returned_string> r(
desc.printValueAsJSON((State *)&state, strict, &ctx, copyToStore));
if (!r) {
return nix::ExternalValueBase::printValueAsJSON(state, strict, context,
copyToStore);
}
return nlohmann::json::parse(r->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((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,
GCRef *gc) {
if (context)
context->last_err_code = NIX_OK;
try {
auto ret = new
#ifdef HAVE_BOEHMGC
(GC)
#endif
NixCExternalValue(*desc, v);
if (gc)
gc->ptr = 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
}