mirror of
https://github.com/NixOS/nix
synced 2025-06-27 04:21:16 +02:00
libutil: add C bindings
This commit is contained in:
parent
c0b6907ccd
commit
4702317506
5 changed files with 437 additions and 1 deletions
148
src/libutil/nix_api_util.cc
Normal file
148
src/libutil/nix_api_util.cc
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "nix_api_util.h"
|
||||
#include "config.hh"
|
||||
#include "error.hh"
|
||||
#include "nix_api_util_internal.h"
|
||||
#include "util.hh"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <typeinfo>
|
||||
|
||||
nix_c_context *nix_c_context_create() { return new nix_c_context(); }
|
||||
|
||||
void nix_c_context_free(nix_c_context *context) { delete context; }
|
||||
|
||||
nix_err nix_context_error(nix_c_context *context) {
|
||||
if (context == nullptr) {
|
||||
throw;
|
||||
}
|
||||
try {
|
||||
throw;
|
||||
} catch (nix::Error &e) {
|
||||
/* Storing this exception is annoying, take what we need here */
|
||||
context->last_err = e.what();
|
||||
context->info = e.info();
|
||||
int status;
|
||||
const char *demangled =
|
||||
abi::__cxa_demangle(typeid(e).name(), 0, 0, &status);
|
||||
if (demangled) {
|
||||
context->name = demangled;
|
||||
// todo: free(demangled);
|
||||
} else {
|
||||
context->name = typeid(e).name();
|
||||
}
|
||||
context->last_err_code = NIX_ERR_NIX_ERROR;
|
||||
return context->last_err_code;
|
||||
} catch (const std::exception &e) {
|
||||
context->last_err = e.what();
|
||||
context->last_err_code = NIX_ERR_UNKNOWN;
|
||||
return context->last_err_code;
|
||||
}
|
||||
// unreachable
|
||||
}
|
||||
|
||||
nix_err nix_set_err_msg(nix_c_context *context, nix_err err, const char *msg) {
|
||||
if (context == nullptr) {
|
||||
// todo last_err_code
|
||||
throw new nix::Error("Nix C api error", msg);
|
||||
}
|
||||
context->last_err_code = err;
|
||||
context->last_err = msg;
|
||||
return err;
|
||||
}
|
||||
|
||||
const char *nix_version_get() { return PACKAGE_VERSION; }
|
||||
|
||||
// Implementations
|
||||
nix_err nix_setting_get(nix_c_context *context, const char *key, char *value,
|
||||
int n) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
std::map<std::string, nix::AbstractConfig::SettingInfo> settings;
|
||||
nix::globalConfig.getSettings(settings);
|
||||
if (settings.contains(key))
|
||||
return nix_export_std_string(context, settings[key].value, value, n);
|
||||
else {
|
||||
return nix_set_err_msg(context, NIX_ERR_KEY, "Setting not found");
|
||||
}
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err nix_setting_set(nix_c_context *context, const char *key,
|
||||
const char *value) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
if (nix::globalConfig.set(key, value))
|
||||
return NIX_OK;
|
||||
else {
|
||||
return nix_set_err_msg(context, NIX_ERR_KEY, "Setting not found");
|
||||
}
|
||||
}
|
||||
|
||||
nix_err nix_libutil_init(nix_c_context *context) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
nix::initLibUtil();
|
||||
return NIX_OK;
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
const char *nix_err_msg(nix_c_context *context,
|
||||
const nix_c_context *read_context, unsigned int *n) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
if (read_context->last_err) {
|
||||
if (n)
|
||||
*n = read_context->last_err->size();
|
||||
return read_context->last_err->c_str();
|
||||
}
|
||||
nix_set_err_msg(context, NIX_ERR_UNKNOWN, "No error message");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nix_err nix_err_name(nix_c_context *context, const nix_c_context *read_context,
|
||||
char *value, int n) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
if (read_context->last_err_code != NIX_ERR_NIX_ERROR) {
|
||||
return nix_set_err_msg(context, NIX_ERR_UNKNOWN,
|
||||
"Last error was not a nix error");
|
||||
}
|
||||
return nix_export_std_string(context, read_context->name, value, n);
|
||||
}
|
||||
|
||||
nix_err nix_err_info_msg(nix_c_context *context,
|
||||
const nix_c_context *read_context, char *value,
|
||||
int n) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
if (read_context->last_err_code != NIX_ERR_NIX_ERROR) {
|
||||
return nix_set_err_msg(context, NIX_ERR_UNKNOWN,
|
||||
"Last error was not a nix error");
|
||||
}
|
||||
return nix_export_std_string(context, read_context->info->msg.str(), value,
|
||||
n);
|
||||
}
|
||||
|
||||
nix_err nix_err_code(nix_c_context *context,
|
||||
const nix_c_context *read_context) {
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
return read_context->last_err_code;
|
||||
}
|
||||
|
||||
// internal
|
||||
nix_err nix_export_std_string(nix_c_context *context,
|
||||
const std::string_view str, char *dest,
|
||||
unsigned int n) {
|
||||
size_t i = str.copy(dest, n - 1);
|
||||
dest[i] = 0;
|
||||
if (i == n - 1) {
|
||||
return nix_set_err_msg(context, NIX_ERR_OVERFLOW,
|
||||
"Provided buffer too short");
|
||||
} else
|
||||
return NIX_OK;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue