Commit 9a9d773b authored by Julian Bouzas's avatar Julian Bouzas
Browse files

wptoml: add new library to parse TOML files

parent 6e4752a7
image: registry.freedesktop.org/pipewire/pipewire/fedora:31
variables:
DEPENDENCIES: gtk-doc gobject-introspection-devel
DEPENDENCIES: gtk-doc gobject-introspection-devel cmake gcc-c++
build:
before_script:
......
subdir('wptoml')
subdir('wp')
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/* C++ STL */
#include <functional>
/* CPPTOML */
#include <include/cpptoml.h>
/* TOML */
#include "private.h"
#include "array.h"
namespace wp {
namespace toml {
/* The Array class */
class Array {
public:
/* The data of the array */
using Data = std::shared_ptr<const cpptoml::array>;
/* The for each function for values */
template <typename T>
using ForEachValueFunction = std::function<void(const T*, gpointer)>;
/* The for each function for arrays of values */
using ForEachArrayFunction = std::function<void(WpTomlArray *, gpointer )>;
/* Constructor */
Array(Data data) :
data_(std::move(data)) {
}
/* Destructor */
virtual ~Array() {
}
/* Calls the given callback for values */
template <typename T>
void ForEachValue(ForEachValueFunction<T> func, gpointer user_data) const {
for (const std::shared_ptr<cpptoml::value<T>>& v : data_->array_of<T>()) {
if (v) {
const T val = v->get();
func(&val, user_data);
} else {
func(nullptr, user_data);
}
}
}
/* Calls the given callback for arrays of values */
void ForEachArray(ForEachArrayFunction func, gpointer user_data) const {
for (const Data& val : data_->nested_array()) {
gconstpointer d = static_cast<gconstpointer>(&val);
g_autoptr (WpTomlArray) a = wp_toml_array_new(d);
func(a, user_data);
}
}
private:
/* Copy Constructor */
Array(const Array&) = delete;
/* Move Constructor */
Array(Array &&) = delete;
/* Copy-Assign Constructor */
Array& operator=(const Array&) = delete;
/* Move-Assign Constructr */
Array& operator=(Array &&) = delete;
private:
/* The data array */
const Data data_;
};
} /* namespace toml */
} /* namespace wp */
struct _WpTomlArray
{
const wp::toml::Array *data;
};
G_DEFINE_BOXED_TYPE(WpTomlArray, wp_toml_array, wp_toml_array_ref,
wp_toml_array_unref)
WpTomlArray *
wp_toml_array_new (gconstpointer data)
{
g_return_val_if_fail (data, nullptr);
try {
g_autoptr(WpTomlArray) self = g_rc_box_new (WpTomlArray);
/* Set the data */
const wp::toml::Array::Data *d =
static_cast<const wp::toml::Array::Data *>(data);
self->data = new wp::toml::Array {*d};
return static_cast<WpTomlArray *>(g_steal_pointer (&self));
} catch (std::bad_alloc& ba) {
g_critical ("Could not create WpTomlArray: %s", ba.what());
return nullptr;
} catch (...) {
g_critical ("Could not create WpTomlArray");
return nullptr;
}
}
WpTomlArray *
wp_toml_array_ref (WpTomlArray * self)
{
return static_cast<WpTomlArray *>(
g_rc_box_acquire (static_cast<gpointer>(self)));
}
void
wp_toml_array_unref (WpTomlArray * self)
{
static void (*free_func)(gpointer) = [](gpointer p){
WpTomlArray *a = static_cast<WpTomlArray *>(p);
delete a->data;
};
g_rc_box_release_full (self, free_func);
}
void
wp_toml_array_for_each_boolean (const WpTomlArray *self,
WpTomlArrayForEachBoolFunc func, gpointer user_data)
{
self->data->ForEachValue<bool>([&](const bool *v, gpointer d){
if (v) {
const gboolean b = *v ? TRUE : FALSE;
func(&b, d);
} else {
func(nullptr, d);
}
}, user_data);
}
void
wp_toml_array_for_each_int64 (const WpTomlArray *self,
WpTomlArrayForEachInt64Func func, gpointer user_data)
{
self->data->ForEachValue<int64_t>(func, user_data);
}
void
wp_toml_array_for_each_double (const WpTomlArray *self,
WpTomlArrayForEachDoubleFunc func, gpointer user_data)
{
self->data->ForEachValue<double>(func, user_data);
}
void
wp_toml_array_for_each_string (const WpTomlArray *self,
WpTomlArrayForEachStringFunc func, gpointer user_data)
{
self->data->ForEachValue<std::string>([&](const std::string *v, gpointer d){
func(v ? v->c_str() : nullptr, d);
}, user_data);
}
void
wp_toml_array_for_each_array (const WpTomlArray *self,
WpTomlArrayForEachArrayFunc func, gpointer user_data)
{
self->data->ForEachArray(func, user_data);
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WP_TOML_ARRAY_H__
#define __WP_TOML_ARRAY_H__
#include <glib-object.h>
#include <stdint.h>
G_BEGIN_DECLS
/* WpTomlArray */
GType wp_toml_array_get_type (void);
typedef struct _WpTomlArray WpTomlArray;
WpTomlArray * wp_toml_array_ref (WpTomlArray * self);
void wp_toml_array_unref (WpTomlArray * self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WpTomlArray, wp_toml_array_unref)
/* API */
typedef void (*WpTomlArrayForEachBoolFunc)(const gboolean *, gpointer);
void wp_toml_array_for_each_boolean (const WpTomlArray *self,
WpTomlArrayForEachBoolFunc func, gpointer user_data);
typedef void (*WpTomlArrayForEachInt64Func)(const int64_t *, gpointer);
void wp_toml_array_for_each_int64 (const WpTomlArray *self,
WpTomlArrayForEachInt64Func func, gpointer user_data);
typedef void (*WpTomlArrayForEachDoubleFunc)(const double *, gpointer);
void wp_toml_array_for_each_double (const WpTomlArray *self,
WpTomlArrayForEachDoubleFunc func, gpointer user_data);
typedef void (*WpTomlArrayForEachStringFunc)(const char *, gpointer);
void wp_toml_array_for_each_string (const WpTomlArray *self,
WpTomlArrayForEachStringFunc func, gpointer user_data);
typedef void (*WpTomlArrayForEachArrayFunc)(WpTomlArray *, gpointer);
void wp_toml_array_for_each_array (const WpTomlArray *self,
WpTomlArrayForEachArrayFunc func, gpointer user_data);
G_END_DECLS
#endif
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/* CPPTOML */
#include <include/cpptoml.h>
/* TOML */
#include "private.h"
#include "file.h"
struct _WpTomlFile
{
char *name;
WpTomlTable *table;
};
G_DEFINE_BOXED_TYPE(WpTomlFile, wp_toml_file, wp_toml_file_ref,
wp_toml_file_unref)
WpTomlFile *
wp_toml_file_new (const char *name)
{
g_return_val_if_fail (name, nullptr);
try {
g_autoptr (WpTomlFile) self = g_rc_box_new (WpTomlFile);
/* Set the name */
self->name = g_strdup (name);
/* Set the table by parsing the file */
std::shared_ptr<cpptoml::table> data = cpptoml::parse_file(name);
self->table = wp_toml_table_new (static_cast<gconstpointer>(&data));
return static_cast<WpTomlFile *>(g_steal_pointer (&self));
} catch (std::bad_alloc& ba) {
g_critical ("Could not create WpTomlFile from '%s': %s", name, ba.what());
return nullptr;
} catch (...) {
g_critical ("Could not create WpTomlFile from '%s'", name);
return nullptr;
}
}
WpTomlFile *
wp_toml_file_ref (WpTomlFile * self)
{
return static_cast<WpTomlFile *>(
g_rc_box_acquire (static_cast<gpointer>(self)));
}
void
wp_toml_file_unref (WpTomlFile * self)
{
static void (*free_func)(gpointer) = [](gpointer p){
WpTomlFile *f = static_cast<WpTomlFile *>(p);
g_free (f->name);
f->name = nullptr;
wp_toml_table_unref (f->table);
f->table = nullptr;
};
g_rc_box_release_full (self, free_func);
}
const char *
wp_toml_file_get_name (const WpTomlFile *self)
{
return self->name;
}
WpTomlTable *
wp_toml_file_get_table (const WpTomlFile *self)
{
return wp_toml_table_ref (self->table);
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WP_TOML_FILE_H__
#define __WP_TOML_FILE_H__
#include <glib-object.h>
#include "table.h"
G_BEGIN_DECLS
/* WpTomlFile */
GType wp_toml_file_get_type (void);
typedef struct _WpTomlFile WpTomlFile;
WpTomlFile *wp_toml_file_new (const char *name);
WpTomlFile * wp_toml_file_ref (WpTomlFile * self);
void wp_toml_file_unref (WpTomlFile * self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WpTomlFile, wp_toml_file_unref)
/* API */
const char *wp_toml_file_get_name (const WpTomlFile *self);
WpTomlTable *wp_toml_file_get_table (const WpTomlFile *self);
G_END_DECLS
#endif
wptoml_lib_sources = [
'array.cpp',
'table.cpp',
'file.cpp',
]
wptoml_lib_headers = [
'wptoml.h',
'array.h',
'table.h',
'file.h',
]
wptoml_lib = static_library('wptoml-' + wireplumber_api_version,
wptoml_lib_sources,
cpp_args : [
'-D_GNU_SOURCE',
'-DG_LOG_USE_STRUCTURED',
'-DG_LOG_DOMAIN="libwptoml"',
],
install: false,
include_directories: wp_lib_include_dir,
dependencies : [gobject_dep, cpptoml_dep],
)
wptoml_dep = declare_dependency(
link_with: wptoml_lib,
include_directories: wp_lib_include_dir,
dependencies: [gobject_dep]
)
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WP_TOML_PRIVATE_H__
#define __WP_TOML_PRIVATE_H__
#include <glib-object.h>
G_BEGIN_DECLS
/* Forward declaration */
struct _WpTomlArray;
typedef struct _WpTomlArray WpTomlArray;
struct _WpTomlTable;
typedef struct _WpTomlTable WpTomlTable;
WpTomlArray * wp_toml_array_new (gconstpointer data);
WpTomlTable * wp_toml_table_new (gconstpointer data);
G_END_DECLS
#endif
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/* C++ STL */
#include <functional>
/* CPPTOML */
#include <include/cpptoml.h>
/* TOML */
#include "private.h"
#include "table.h"
namespace wp {
namespace toml {
/* The Table class */
class Table {
public:
/* The data of the array */
using Data = std::shared_ptr<const cpptoml::table>;
/* Constructor */
Table(Data data) :
data_(std::move(data)) {
}
/* Destructor */
virtual ~Table() {
}
/* Determines if this table contains the given key */
bool Contains(const std::string& key) const {
return data_->contains(key);
}
/* Gets a value */
template <typename T>
bool GetValue(const std::string& key, T *val, bool qualified) const {
g_return_val_if_fail (val, false);
const cpptoml::option<T> opt =
qualified ? data_->get_qualified_as<T>(key) : data_->get_as<T>(key);
if (!opt)
return false;
*val = *opt;
return true;
}
/* Gets an array of values */
std::shared_ptr<const cpptoml::array> GetArray(const std::string& key,
bool qualified) const {
return qualified ? data_->get_array_qualified(key) : data_->get_array(key);
}
/* Gets an array of tables */
std::shared_ptr<const cpptoml::table_array> GetTableArray(
const std::string& key, bool qualified) const {
return qualified ? data_->get_table_array_qualified(key) :
data_->get_table_array(key);
}
/* Gets a nested table */
Data GetTable(const std::string& key, bool qualified) const {
return qualified ? data_->get_table_qualified(key) : data_->get_table(key);
}
private:
/* Copy Constructor */
Table(const Table&) = delete;
/* Move Constructor */
Table(Table &&) = delete;
/* Copy-Assign Constructor */
Table& operator=(const Table&) = delete;
/* Move-Assign Constructr */
Table& operator=(Table &&) = delete;
private:
/* The data table */
const Data data_;
};
/* The Array Table class */
class TableArray {
public:
/* The data of the array */
using Data = std::shared_ptr<const cpptoml::table_array>;
/* The for each function for arrays of tables */
using ForEachFunction = std::function<void(WpTomlTable *, gpointer)>;
/* Constructor */
TableArray(Data data) :
data_(std::move(data)) {
}
/* Destructor */
virtual ~TableArray() {
}
/* Calls the given callback for arrays of values */
void ForEach(ForEachFunction func, gpointer user_data) const {
for (const auto& table : *data_) {
gconstpointer p = static_cast<gconstpointer>(&table);
g_autoptr (WpTomlTable) t = wp_toml_table_new(p);
func(t, user_data);
}
}
private:
/* Copy Constructor */
TableArray(const TableArray&) = delete;
/* Move Constructor */
TableArray(TableArray &&) = delete;
/* Copy-Assign Constructor */
TableArray& operator=(const TableArray&) = delete;
/* Move-Assign Constructr */
TableArray& operator=(TableArray &&) = delete;
private:
/* The data array */
const Data data_;
};
} /* namespace toml */
} /* namespace wp */
struct _WpTomlTable
{
wp::toml::Table *data;
};
G_DEFINE_BOXED_TYPE(WpTomlTable, wp_toml_table, wp_toml_table_ref,
wp_toml_table_unref)
struct _WpTomlTableArray
{
const wp::toml::TableArray *data;
};
G_DEFINE_BOXED_TYPE(WpTomlTableArray, wp_toml_table_array,
wp_toml_table_array_ref, wp_toml_table_array_unref)
WpTomlTable *
wp_toml_table_new (gconstpointer data)
{
g_return_val_if_fail (data, nullptr);
try {
g_autoptr (WpTomlTable) self = g_rc_box_new (WpTomlTable);
/* Set the data */
const wp::toml::Table::Data *d =
static_cast<const wp::toml::Table::Data *>(data);
self->data = new wp::toml::Table {*d};
return static_cast<WpTomlTable *>(g_steal_pointer (&self));
} catch (std::bad_alloc& ba) {
g_critical ("Could not create WpTomlTable: %s", ba.what());
return nullptr;
} catch (...) {
g_critical ("Could not create WpTomlTable");
return nullptr;
}
}
WpTomlTable *
wp_toml_table_ref (WpTomlTable * self)
{
return static_cast<WpTomlTable *>(
g_rc_box_acquire (static_cast<gpointer>(self)));
}
void
wp_toml_table_unref (WpTomlTable * self)
{
static void (*free_func)(gpointer) = [](gpointer p){
WpTomlTable *t = static_cast<WpTomlTable *>(p);
delete t->data;
};
g_rc_box_release_full (self, free_func);
}
static WpTomlTableArray *
wp_toml_table_array_new (gconstpointer data)
{
g_return_val_if_fail (data, nullptr);
try {
g_autoptr (WpTomlTableArray) self = g_rc_box_new (WpTomlTableArray);
/* Set the data */
const wp::toml::TableArray::Data *d =
static_cast<const wp::toml::TableArray::Data *>(data);
self->data = new wp::toml::TableArray {*d};
return static_cast<WpTomlTableArray *>(g_steal_pointer (&self));
} catch (std::bad_alloc& ba) {
g_critical ("Could not create WpTomlTableArray: %s", ba.what());
return nullptr;
} catch (...) {
g_critical ("Could not create WpTomlTableArray");
return nullptr;
}
}