<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 3, 2020 at 3:22 AM 魏艳艳 <<a href="mailto:wyygrowing1224@163.com">wyygrowing1224@163.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="line-height:1.7;color:rgb(0,0,0);font-size:14px;font-family:Arial"><div style="margin:0px">Dear!</div><div style="margin:0px"> I've tried to write configurations using UCI API in my projects, but they often cause my processes to crash, I don't know why?I hope you can help me。</div><div style="margin:0px">1、platform:X86</div><div style="margin:0px">This is the information that my Program crashed</div><div style="margin:0px"><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:20px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(238,240,242);display:inline;float:none">(gdb) where<br>#0 0x00007fef72046277 in raise () from /lib64/libc.so.6<br>#1 0x00007fef72047968 in abort () from /lib64/libc.so.6<br>#2 0x00007fef72088d37 in __libc_message () from /lib64/libc.so.6<br>#3 0x00007fef72091499 in _int_free () from /lib64/libc.so.6<br>#4 0x00007fef723df3ef in uci_free_element (e=0xa63d50) at /home/uci/list.c:72<br>#5 0x00007fef723df573 in uci_free_package (package=package@entry=0xa63380) at /home/uci/list.c:283<br>#6 0x00007fef723dfb0d in uci_cleanup (ctx=0xa64300) at /home/uci/libuci.c:126<br>#7 0x00007fef723dfb6b in uci_free_context (ctx=0xa64300) at /home/uci/libuci.c:80<br>#8 0x0000000000402876 in </span><span style="font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:20px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(238,240,242);display:inline;float:none;color:rgb(221,64,50)">uci_set_value </span><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:20px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(238,240,242);display:inline;float:none">(path=0x40cf59 "/tmp/DataCollection/MODMAN", config=0x40cf51 "rundata", section=0x40cf43 "modmanruninfo", <br> option=0x40cfbf "akMODMANVTxMuteOpenAMIP", value=0x61b780 <g_Mcastinfo> "0") at ft_uci.c:446<br>#9 0x0000000000403dec in Write_Mcast_Data (def=1) at ft_daq.c:166<br>#10 0x000000000040426e in main (argc=1, argv=0x7ffe84fa78c8) at ft_daq.c:264</span></div><div style="margin:0px"><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:20px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(238,240,242);display:inline;float:none"><br></span></div><div style="margin:0px">2、This is the function that writes the configuration file,My program calls uci_set_value function 20 times for 1s.<br>/*****************************************************************/<br>void uci_set_value(char *path, char *config, char *section, char *option, char *value)<br>{<br> struct uci_context *ctx = NULL;<br> struct uci_ptr ptr;<br> int ret = UCI_OK;<br> char str[128] = {0};<br> char filepath[128] = {0};<br><br> ctx = uci_alloc_context();<br> if (!ctx)<br> {<br> ULOG_ERR("uci_alloc_context error, config=%s,section=%s,option=%s,value=%s\n", config, section, option, value);<br> return;<br> }<br> if (NULL != path)<br> {<br> uci_set_confdir(ctx, path);<br> }<br> <br> memset(&ptr, 0, sizeof(ptr));<br> memset(str, 0 , sizeof(str));<br> sprintf(str, "%s.%s.%s=%s", config, section, option, value);<br> <br> if (uci_lookup_ptr(ctx, &ptr, str, true) != 0) <br> {<br> ULOG_ERR("uci_lookup_ptr error, str=%s\n", str);<br> uci_free_context(ctx);<br> return;<br> }<br> memset(filepath, 0, sizeof(filepath));<br> sprintf(filepath, "%s/%s", path, config);<br> <br> if ((0 != strcmp(ctx->confdir, path)) || (0 != strcmp(filepath, ptr.p->path)))<br> {<br> if (ptr.p)<br> {<br> uci_unload(ctx, ptr.p); <br> }<br> uci_free_context(ctx);<br> return;<br> }<br> <br> ret = uci_set(ctx, &ptr);<br> if (0 == ret)<br> {<br> ret = uci_commit(ctx, &ptr.p, false);<br> }<br> else<br> {<br> ULOG_ERR("uci_set error, str=%s\n", str);<br> }<br> <br> if (ptr.p)<br> {<br> uci_unload(ctx, ptr.p); <br> }</div><div style="margin:0px"><span style="color:rgb(221,64,50)">// Program terminated with signal 6, Aborted.<br></span></div><div style="margin:0px"><span style="color:rgb(221,64,50)"> </span><span style="color:rgb(0,0,0)">uci_free_context(ctx);</span></div><div style="margin:0px"><br> return ;<br>}</div><div style="margin:0px">/*****************************************************************/</div><div style="margin:0px"><br></div><div style="margin:0px">3、My config file</div><div style="margin:0px">config modman 'modmanruninfo'<br> option akTestDID 'unknown'<br> option akTestUptime 'unknown'<br> option akTestSatelliteNetworkID 'unknown'<br></div><div style="margin:0px"> akMODMANVTxMuteOpenAMIP 'unknown'</div></div></blockquote><div><br></div><div><br></div><div><br></div><div>I don't know what's wrong with your code above, and I haven't tried to analyze it for mistakes.</div><div><br></div><div>I'm replying to you because I wrote a C++ wrapper around UCI a while ago, that involved documenting some of the conventions of the libuci API.</div><div><br></div><div>I'm providing it here as use-at-your-own-risk, and will not provide updates, bug fixes, security fixes, or really anything, pertaining to this code. There are almost certainly bugs in this code, because I do not use it. I abandoned this approach to interacting with the UCI subsystem in favor of the rpcd UCI module.<br></div><div><br></div><div>Released under the same license as libUCI itself (LGPL 2.1).</div><div><br></div><div>It may help you understand the libuci c API. It may not.<br></div><div><br></div><div><pre>/** \file
*
*/
#include <string>
#include <vector>
#include <utility>
#include <string_view>
#include "uci.h"
#ifndef LIBUCIXX_PARSE_UCI_CONFIG_FILE_H_A2CD8106_1003_4A6D_9A46_4A128EA83262
#define LIBUCIXX_PARSE_UCI_CONFIG_FILE_H_A2CD8106_1003_4A6D_9A46_4A128EA83262
#pragma once
namespace libucixx
{
namespace impl
{
/** \class ScopeGuard
* The class \c ScopeGuard provides a mechanism to call \c operator() on the object
* provided as the constructor parameter for the \c ScopeGuard object when \c ScopeGuard
* has it's destructor called. This provides a guaranteed, exception safe, way of ensuring
* that cleanup operations are called at end of scope.
*/
template<typename T>
struct ScopeGuard final
{
/**
* Does nothing more than store the parameter in a member variable.
*/
ScopeGuard(T t)
: m_t(std::move(t))
{ }
/**
* Calls the stored object's \c operator() function.
*/
~ScopeGuard()
{
m_t();
}
private:
T m_t; ///< The stored object to invoke on destruction.
}; // struct ScopeGuard
/**
* Template deduction guide for \c ScopeGuard that avoids the need for a factory function.
*/
template<typename T> ScopeGuard(T t) -> ScopeGuard<T>;
//-----------------------------------------------------------------------------
/**
* Extracts error string from the \c uci_context provided,
* and throws a runtime exception with its contents.
*/
inline void throw_uci_error(uci_context & ctx)
{
char * dest = nullptr;
const ScopeGuard destGuard([&dest](void){ free(dest); });
uci_get_errorstr(&ctx, &dest, nullptr);
if(dest)
{
throw std::runtime_error(dest);
}
else
{
throw std::runtime_error("Unknown UCI error");
}
} // throw_uci_error()
//-----------------------------------------------------------------------------
/**
* Assert that the provided \c std::string_view is nul terminated.
*/
inline void assert_nul_terminated(std::string_view str)
{
assert(str.data() + str.size() == '\0');
}
} // namespace impl
//-----------------------------------------------------------------------------
/**
* Forward declare types.
*/
struct UciOption;
struct UciSection;
struct UciPackage;
struct UciContext;
//-----------------------------------------------------------------------------
/** \class UciOption
*
*/
struct UciOption
{
private:
friend struct UciSection;
struct constructor_access{}; ///< Provides access to the constructor for friends.
public:
/**
* Constructs \c UciOption. Use \c UciSection::get_option() to acquire a \c UciOption.
*
* \param key - The \c constructor_access type that's only visible to friend classes.
* Used to guard against improper use of \c UciOption.
* \param pSec - The \c UciSection that this \c UciOption belongs to.
* \param pUciOpt - The \c uci_option from libuci.
*/
UciOption(constructor_access key, std::shared_ptr<UciSection> pSec, uci_option * pUciOpt);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this \c UciOption belongs to.
*
* \return The name of the this option.
*/
std::string_view get_name(void);
/**
* \return TRUE - This option represents a list of values
* FALSE - This option represents a scalar value
*/
bool is_list(void);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this option belongs to.
*
* \return The value of the this option.
*/
std::string_view get_value(void);
/**
* \param value - Nul terminated value to set this option to.
*/
void set_value(std::string_view value);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this option belongs to.
*
* \return The value of the this option as a list of values.
*/
std::vector<std::string_view> get_list(void);
/**
* \param list - vector of nul terminated \c std::string_views to
* replace the current list of option values with.
*/
void set_list(std::vector<std::string_view> list);
/**
* \param value - Nul terminated value to add to this option's list.
*/
void add_to_list(std::string_view);
/**
* \param value - Nul terminated value to remove from this option's list.
*/
void remove_from_list(std::string_view);
private:
/**
* \return The \c uci_context held by the \c UciContext class
* used to acquire this UciOption via the \c UciSection and
* \c UciPackage shared pointers.
*/
uci_context * get_uci_context(void);
private:
uci_option * m_pUciOpt; ///< The \c struct uci_option from libuci. Lifetime managed by the associated \c UciPackage object.
std::shared_ptr<UciSection> m_pSec; ///< Shared pointer to \c UciSection that this option belongs to. Keeps data retrieved from libuci alive.
}; // UciOption
//-----------------------------------------------------------------------------
/** \class UciSection
*
*/
struct UciSection : public std::enable_shared_from_this<UciSection>
{
private:
friend struct UciPackage;
struct constructor_access{}; ///< Provides access to the constructor for friends.
public:
/**
* Constructs \c UciSection. Use \c UciPackage::get_section() to acquire a \c UciSection.
*
* \param key - The \c constructor_access type that's only visible to friend classes.
* Used to guard against improper use of \c UciSection.
* \param pSec - The \c UciPackage that this \c UciSection belongs to.
* \param pUciOpt - The \c uci_section from libuci.
*/
UciSection(constructor_access key, std::shared_ptr<UciPackage> pPkg, uci_section * pUciSec);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this \c UciSection belongs to.
*
* \return The name of the this section.
*/
std::string_view get_name(void);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this \c UciSection belongs to.
*
* \return The type of this section.
*/
std::string_view get_type(void);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this \c UciSection belongs to.
*
* \return The list of options that this section contains.
*/
std::vector<std::string_view> list_options(void);
/**
* Looks up the UciOption associated with the provided nul-terminated name.
*
* \param name - the name of the option.
*/
std::shared_ptr<UciOption> get_option(std::string_view name);
/**
* Creates and inserts a new string-type option with the provided value.
*
* \param name - the name of the option.
* \param value - the value of the option.
*/
std::shared_ptr<UciOption> add_option(std::string_view name, std::string_view value);
/**
* Creates and inserts a new list-type option with the provided value.
*
* \param name - the name of the option.
* \param value - the values of the option.
*/
std::shared_ptr<UciOption> add_option(std::string_view name, std::list<std::string_view> value);
/**
* Deletes the option with the provided name.
*
* \param name - the option to delete.
*/
void delete_option(std::string_view name);
/**
* Change the index of this section.
*
* \param the index to change this section to.
*/
void set_section_index(int idx);
private:
friend struct UciOption;
/**
* \return The \c uci_context held by the \c UciContext class used
* to acquire this \c UciSection via the \c UciPackage shared pointer.
*/
uci_context * get_uci_context(void);
private:
uci_section * m_pUciSec; ///<
std::shared_ptr<UciPackage> m_pPkg; ///<
}; // struct UciSection
//-----------------------------------------------------------------------------
/** \class UciPackage
*
*/
struct UciPackage : public std::enable_shared_from_this<UciPackage>
{
private:
friend struct UciContext;
struct constructor_access{}; ///< Provides access to the constructor for friends.
public:
/**
* \param key - The \c constructor_access type that's only visible to friend classes.
* Used to guard against improper use of \c UciPackage.
* \param pSec - The \c UciContext that this UciPackage belongs to.
* \param pUciOpt - The \c uci_package from libuci.
*/
UciPackage(constructor_access key, std::shared_ptr<UciContext> pCtx, uci_package * pUciPkg);
/**
* Ensures that this UciPackage, and everything that's associated with it, is unloaded from libuci.
*/
~UciPackage(void);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of this \c UciPackage.
*
* \return The name of this package.
*/
std::string_view get_name(void);
/**
* \note The returned \c std::string_view's lifetime is the same as the
* lifetime of the \c UciPackage that this \c UciSection belongs to.
*
* \return A collection of section names.
*/
std::vector<std::string_view> list_sections(void);
/**
* \param name - A nul-terminated string indicating the desired section name.
* \return a UciSection representing the section indicated by name.
*/
std::shared_ptr<UciSection> get_section(std::string_view name);
/**
* \param name - A nul-terminated string indicating the desired section name.
* \return a UciSection representing the newly added section.
*/
std::shared_ptr<UciSection> add_section(std::string_view type, std::string_view name = std::string_view());
/**
* Delete a section by name.
*
* \param name - A nul-terminated string indicating the desired section name.
*/
void delete_section(std::string_view name);
/**
* Saves the changes that have been made to this UciPackage to disk as a delta.
* Use \c UciPackage::commit() to apply these changes.
*/
void save(void);
/**
* Applies all deltas saved to disk to this package'S config file.
*
* \note Warning! Invalidates all UciSections and UciOptions derived from this UciPackage
*
* \param overwrite - ???
*/
void commit(bool overwrite = true);
private:
friend struct UciSection;
/**
* \return The \c uci_context held by the \c UciContext class
* used to acquire this \c UciPackage shared pointer.
*/
uci_context * get_uci_context(void);
private:
uci_package * m_pUciPkg; ///<
std::shared_ptr<UciContext> m_pCtx; ///<
}; // struct UciPackage
//-----------------------------------------------------------------------------
/** \class UciContext
*
*/
struct UciContext : public std::enable_shared_from_this<UciContext>
{
/**
* Allocates a libuci \c struct uci_context.
*/
UciContext(void);
/**
* Frees the libuci \c struct uci_context.
*/
~UciContext(void);
/**
* \return List of UCI packages available in the configured config directory.
*/
std::vector<std::string> list_packages(void);
/**
* \param name - the desired package name.
*
* \note When the UciPackage's shared pointer is deleted, the named package will
* be unloaded from libuci.
*
* \return A shared pointer to a UciPackage representing the indicated package name.
*/
std::shared_ptr<UciPackage> load_package(std::string_view name);
/**
* Sets the directory that libuci will use to save deltas.
*
* \param dir - the indicated, nul-terminatred, directory.
*/
void set_save_dir(std::string_view dir);
/**
* Sets the directory that libuci will search from config files.
*
* \param dir - the indicated, nul-terminatred, directory.
*/
void set_config_dir(std::string_view dir);
/**
* Adds an additional directory that libuci will use to search for deltas.
*
* \param dir - the indicated, nul-terminatred, directory.
*/
void add_delta_path(std::string_view dir);
/**
* Sets the backend that libuci will use for storage.
*
* \param backend - the indicated, nul-terminatred, backend.
*/
void set_backend(std::string_view backend);
private:
friend struct UciPackage;
/**
* \return the libuci \c struct uci_context.
*/
uci_context * get_uci_context(void);
private:
uci_context * m_pUciCtx; ///<
}; // struct UciContext
//-----------------------------------------------------------------------------
// Inline functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Inlines of UciOption
//-----------------------------------------------------------------------------
inline UciOption::UciOption(constructor_access, std::shared_ptr<UciSection> pSec, uci_option * pUciOpt)
: m_pSec(std::move(pSec))
, m_pUciOpt(pUciOpt)
{
assert(nullptr != m_pSec);
assert(nullptr != m_pUciOpt);
}
inline std::string_view UciOption::get_name(void)
{
return m_pUciOpt-><a href="http://e.name">e.name</a>;
}
inline bool UciOption::is_list(void)
{
return UCI_TYPE_LIST == m_pUciOpt->type;
}
inline std::string_view UciOption::get_value(void)
{
return m_pUciOpt->v.string;
}
inline void UciOption::set_value(std::string_view value)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_add_list(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline std::vector<std::string_view> UciOption::get_list(void)
{
std::vector<std::string_view> list;
{
/*
* List is a list of uci_elements, and in the context of
* a uci_option with type list, each such element's name
* is a value in the list.
*/
uci_element *e = nullptr;
uci_foreach_element(&(m_pUciOpt->v.list), e)
{
list.emplace_back(e->name);
}
}
return list;
}
inline void UciOption::set_list(std::vector<std::string_view> list)
{
assert(false);
//TODO:
// Delete all items and add all the new ones? No clear API option
}
inline void UciOption::add_to_list(std::string_view)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_add_list(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline void UciOption::remove_from_list(std::string_view)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_del_list(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline uci_context * UciOption::get_uci_context(void)
{
return m_pSec->get_uci_context();
}
//-----------------------------------------------------------------------------
// Inlines of UciSection
//-----------------------------------------------------------------------------
inline UciSection::UciSection(constructor_access, std::shared_ptr<UciPackage> pPkg, uci_section * pUciSec)
: m_pPkg(std::move(pPkg))
, m_pUciSec(pUciSec)
{
assert(nullptr != m_pPkg);
assert(nullptr != m_pUciSec);
}
inline std::string_view UciSection::get_name(void)
{
return m_pUciSec-><a href="http://e.name">e.name</a>;
}
inline std::string_view UciSection::get_type(void)
{
return m_pUciSec->type;
}
inline std::vector<std::string_view> UciSection::list_options(void)
{
std::vector<std::string_view> sections;
{
uci_element *e = nullptr;
uci_foreach_element(&(m_pUciSec->options), e)
{
uci_option *o = uci_to_option(e);
sections.emplace_back(o-><a href="http://e.name">e.name</a>);
}
}
return sections;
}
inline std::shared_ptr<UciOption> UciSection::get_option(std::string_view name)
{
impl::assert_nul_terminated(name);
if(uci_option * pOpt = uci_lookup_option(get_uci_context(), m_pUciSec, name.data()); pOpt != nullptr)
{
return std::make_shared<UciOption>(UciOption::constructor_access(), this->shared_from_this(), pOpt);
}
else
{
return {};
}
}
inline std::shared_ptr<UciOption> UciSection::add_option(std::string_view name, std::string_view value)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_set(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline std::shared_ptr<UciOption> UciSection::add_option(std::string_view name, std::list<std::string_view> value)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_set(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline void UciSection::delete_option(std::string_view name)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_delete(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline void UciSection::set_section_index(int idx)
{
if(UCI_OK != uci_reorder_section(get_uci_context(), m_pUciSec, idx))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline uci_context * UciSection::get_uci_context(void)
{
return m_pPkg->get_uci_context();
}
//-----------------------------------------------------------------------------
// Inlines of UciPackage
//-----------------------------------------------------------------------------
inline UciPackage::UciPackage(constructor_access, std::shared_ptr<UciContext> pCtx, uci_package * pUciPkg)
: m_pCtx(std::move(pCtx))
, m_pUciPkg(pUciPkg)
{
assert(nullptr != m_pCtx);
assert(nullptr != m_pUciPkg);
}
inline UciPackage::~UciPackage()
{
if(UCI_OK != uci_unload(get_uci_context(), m_pUciPkg))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline std::string_view UciPackage::get_name(void)
{
return m_pUciPkg-><a href="http://e.name">e.name</a>;
}
inline std::vector<std::string_view> UciPackage::list_sections(void)
{
std::vector<std::string_view> sections;
{
uci_element *e = nullptr;
uci_foreach_element( &m_pUciPkg->sections, e)
{
uci_section *s = uci_to_section(e);
sections.emplace_back(s-><a href="http://e.name">e.name</a>);
}
}
return sections;
}
inline std::shared_ptr<UciSection> UciPackage::get_section(std::string_view name)
{
impl::assert_nul_terminated(name);
if(uci_section * pSec = uci_lookup_section(get_uci_context(), m_pUciPkg, name.data()); pSec != nullptr)
{
return std::make_shared<UciSection>(UciSection::constructor_access(), this->shared_from_this(), pSec);
}
else
{
return {};
}
}
inline std::shared_ptr<UciSection> UciPackage::add_section(std::string_view type, std::string_view name)
{
uci_section * pSec = nullptr;
if(UCI_OK != uci_add_section(get_uci_context(), m_pUciPkg, type.data(), &pSec))
{
impl::throw_uci_error(*get_uci_context());
}
if( ! name.empty())
{
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_rename(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
return std::make_shared<UciSection>(UciSection::constructor_access(), this->shared_from_this(), pSec);
}
inline void UciPackage::delete_section(std::string_view name)
{
assert(false);
uci_ptr ptr;
// Set values to ... something?
if(UCI_OK != uci_delete(get_uci_context(), &ptr))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline void UciPackage::save(void)
{
if(UCI_OK != uci_save(get_uci_context(), m_pUciPkg))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline void UciPackage::commit(bool overwrite)
{
if(UCI_OK != uci_commit(get_uci_context(), &m_pUciPkg, overwrite))
{
impl::throw_uci_error(*get_uci_context());
}
}
inline uci_context * UciPackage::UciPackage::get_uci_context(void)
{
return m_pCtx->get_uci_context();
}
//-----------------------------------------------------------------------------
// Inlines of UciContext
//-----------------------------------------------------------------------------
inline UciContext::UciContext(void)
: m_pUciCtx(uci_alloc_context())
{
assert(nullptr != m_pUciCtx);
}
inline UciContext::~UciContext(void)
{
uci_free_context(m_pUciCtx);
}
inline std::vector<std::string> UciContext::list_packages(void)
{
char **configs = nullptr;
const impl::ScopeGuard configGuard([&configs](void){ free(configs); });
if((UCI_OK != uci_list_configs(m_pUciCtx, &configs)) || ! configs)
{
impl::throw_uci_error(*m_pUciCtx);
}
std::vector<std::string> configvect;
for(char ** p = configs; *p; ++p)
{
configvect.emplace_back(*p);
}
return configvect;
}
inline std::shared_ptr<UciPackage> UciContext::load_package(std::string_view name)
{
// TODO: It would be ideal if there was a way to ensure a UciPackage loaded twice had the
// same lifetime. probably need a std::map<std::string, std::weak_ptr<UciPackage>>;
impl::assert_nul_terminated(name);
uci_package * pUciPkg = nullptr;
if(UCI_OK != uci_load(m_pUciCtx, name.data(), &pUciPkg) || ! pUciPkg)
{
impl::throw_uci_error(*m_pUciCtx);
}
return std::make_shared<UciPackage>(UciPackage::constructor_access(), this->shared_from_this(), pUciPkg);
}
inline void UciContext::set_save_dir(std::string_view dir)
{
impl::assert_nul_terminated(dir);
if(UCI_OK != uci_set_savedir(m_pUciCtx, dir.data()))
{
impl::throw_uci_error(*m_pUciCtx);
}
}
inline void UciContext::set_config_dir(std::string_view dir)
{
impl::assert_nul_terminated(dir);
if(UCI_OK != uci_set_confdir(m_pUciCtx, dir.data()))
{
impl::throw_uci_error(*m_pUciCtx);
}
}
inline void UciContext::add_delta_path(std::string_view dir)
{
impl::assert_nul_terminated(dir);
if(UCI_OK != uci_add_delta_path(m_pUciCtx, dir.data()))
{
impl::throw_uci_error(*m_pUciCtx);
}
}
inline void UciContext::set_backend(std::string_view backend)
{
impl::assert_nul_terminated(backend);
if(UCI_OK != uci_set_backend(m_pUciCtx, backend.data()))
{
impl::throw_uci_error(*m_pUciCtx);
}
}
inline uci_context * UciContext::get_uci_context(void)
{
return m_pUciCtx;
}
} // namespace libucixx
#endif // LIBUCIXX_PARSE_UCI_CONFIG_FILE_H_A2CD8106_1003_4A6D_9A46_4A128EA83262
</pre></div></div></div>