Commit 874f54f1 authored by Daniel Salzman's avatar Daniel Salzman

yp_scheme: add schema merge and dynamic purge operations

parent 4eec99df
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -660,7 +660,7 @@ int conf_parse(
}
// Initialize parser check context.
yp_check_ctx_t *ctx = yp_scheme_check_init(conf->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf->scheme);
if (ctx == NULL) {
ret = KNOT_ENOMEM;
goto parse_error;
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -167,7 +167,7 @@ int conf_io_list(
return list_section(conf()->scheme, &io->key0, io);
}
yp_check_ctx_t *ctx = yp_scheme_check_init(conf()->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf()->scheme);
if (ctx == NULL) {
return KNOT_ENOMEM;
}
......@@ -497,7 +497,7 @@ int conf_io_diff(
return KNOT_EOK;
}
yp_check_ctx_t *ctx = yp_scheme_check_init(conf()->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf()->scheme);
if (ctx == NULL) {
return KNOT_ENOMEM;
}
......@@ -696,7 +696,7 @@ int conf_io_get(
return KNOT_EOK;
}
yp_check_ctx_t *ctx = yp_scheme_check_init(conf()->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf()->scheme);
if (ctx == NULL) {
return KNOT_ENOMEM;
}
......@@ -911,7 +911,7 @@ int conf_io_set(
return KNOT_EINVAL;
}
yp_check_ctx_t *ctx = yp_scheme_check_init(conf()->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf()->scheme);
if (ctx == NULL) {
return KNOT_ENOMEM;
}
......@@ -1118,7 +1118,7 @@ int conf_io_unset(
return KNOT_EOK;
}
yp_check_ctx_t *ctx = yp_scheme_check_init(conf()->scheme);
yp_check_ctx_t *ctx = yp_scheme_check_init(&conf()->scheme);
if (ctx == NULL) {
return KNOT_ENOMEM;
}
......
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -22,6 +22,17 @@
#include "libknot/yparser/yptrafo.h"
#include "libknot/errcode.h"
static size_t scheme_count(
const yp_item_t *src)
{
size_t count = 0;
for (const yp_item_t *item = src; item->name != NULL; item++) {
count++;
}
return count;
}
/*! Initializes the referenced item. */
static int set_ref_item(
yp_item_t *dst,
......@@ -50,13 +61,10 @@ static int set_grp_item(
const yp_item_t *scheme)
{
// Count subitems.
size_t num = 0;
while (src->var.g.sub_items[num].name != NULL) {
num++;
}
size_t count = scheme_count(src->var.g.sub_items);
// Allocate space for subitems + terminal zero item.
size_t memsize = (num + 1) * sizeof(yp_item_t);
size_t memsize = (count + 1) * sizeof(yp_item_t);
dst->sub_items = malloc(memsize);
if (dst->sub_items == NULL) {
return KNOT_ENOMEM;
......@@ -64,7 +72,7 @@ static int set_grp_item(
memset(dst->sub_items, 0, memsize);
// Copy subitems.
for (size_t i = 0; i < num; i++) {
for (size_t i = 0; i < count; i++) {
// The first item is an identifier if multi group.
if (i == 0 && (dst->flags & YP_FMULTI)) {
dst->var.g.id = &dst->sub_items[0];
......@@ -96,6 +104,16 @@ static int set_grp_item(
}
}
if (src->flags & YP_FALLOC) {
dst->var.g.sub_items = malloc(memsize);
if (dst->var.g.sub_items == NULL) {
free(dst->sub_items);
dst->sub_items = NULL;
return KNOT_ENOMEM;
}
memcpy((void *)dst->var.g.sub_items, src->var.g.sub_items, memsize);
}
return KNOT_EOK;
}
......@@ -112,6 +130,15 @@ static int set_item(
// Copy the static data.
*dst = *src;
// Copy item name into dynamic memory.
if (src->flags & YP_FALLOC) {
dst->name = malloc(src->name[0] + 2);
if (dst->name == NULL) {
return KNOT_ENOMEM;
}
memcpy((void *)dst->name, src->name, src->name[0] + 2);
}
// Item type specific preparation.
switch (src->type) {
case YP_TREF:
......@@ -126,6 +153,12 @@ static int set_item(
static void unset_item(
yp_item_t *item)
{
if (item->flags & YP_FALLOC) {
free((void *)item->name);
if (item->flags & YP_FALLOC) {
free((void *)item->var.g.sub_items);
}
}
if (item->sub_items != NULL) {
free(item->sub_items);
}
......@@ -133,6 +166,22 @@ static void unset_item(
memset(item, 0, sizeof(yp_item_t));
}
static int scheme_copy(
yp_item_t *dst,
const yp_item_t *src,
const yp_item_t *scheme)
{
// Copy the scheme.
for (int i = 0; src[i].name != NULL; i++) {
int ret = set_item(dst + i, src + i, scheme);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
int yp_scheme_copy(
yp_item_t **dst,
const yp_item_t *src)
......@@ -141,36 +190,72 @@ int yp_scheme_copy(
return KNOT_EINVAL;
}
// Count scheme items.
size_t scheme_items = 0;
for (const yp_item_t *item = src; item->name != NULL; item++) {
scheme_items++;
// Allocate space for new scheme (+ terminal NULL item).
size_t size = (scheme_count(src) + 1) * sizeof(yp_item_t);
*dst = malloc(size);
if (*dst == NULL) {
return KNOT_ENOMEM;
}
memset(*dst, 0, size);
// Copy the scheme.
int ret = scheme_copy(*dst, src, *dst);
if (ret != KNOT_EOK) {
yp_scheme_free(*dst);
}
// Allocate space for new scheme.
size_t size = (scheme_items + 1) * sizeof(yp_item_t);
return KNOT_EOK;
}
int yp_scheme_merge(
yp_item_t **dst,
const yp_item_t *src1,
const yp_item_t *src2)
{
if (dst == NULL || src1 == NULL || src2 == NULL) {
return KNOT_EINVAL;
}
size_t count1 = scheme_count(src1);
size_t count2 = scheme_count(src2);
// Allocate space for new scheme (+ terminal NULL item).
size_t size = (count1 + count2 + 1) * sizeof(yp_item_t);
*dst = malloc(size);
if (*dst == NULL) {
return KNOT_ENOMEM;
}
memset(*dst, 0, size);
// Copy the scheme.
for (int i = 0; i < scheme_items; i++) {
if (src[i].name == NULL) {
break;
}
// Copy the first scheme.
int ret = scheme_copy(*dst, src1, *dst);
if (ret != KNOT_EOK) {
yp_scheme_free(*dst);
}
int ret = set_item(*dst + i, src + i, *dst);
if (ret != KNOT_EOK) {
yp_scheme_free(*dst);
return ret;
}
// Copy the second scheme.
ret = scheme_copy(*dst + count1, src2, *dst);
if (ret != KNOT_EOK) {
yp_scheme_free(*dst);
}
return KNOT_EOK;
}
void yp_scheme_purge_dynamic(
yp_item_t *scheme)
{
if (scheme == NULL) {
return;
}
for (yp_item_t *item = scheme; item->name != NULL; item++) {
if (item->flags & YP_FALLOC) {
unset_item(item);
}
}
}
void yp_scheme_free(
yp_item_t *scheme)
{
......@@ -228,7 +313,7 @@ const yp_item_t* yp_scheme_find(
}
yp_check_ctx_t* yp_scheme_check_init(
const yp_item_t *scheme)
yp_item_t **scheme)
{
if (scheme == NULL) {
return NULL;
......@@ -287,7 +372,7 @@ static int check_item(
// Check if valid subitem.
node->item = find_item(key, key_len, parent->item->sub_items);
} else {
node->item = find_item(key, key_len, ctx->scheme);
node->item = find_item(key, key_len, *ctx->scheme);
}
if (node->item == NULL) {
return KNOT_YP_EINVAL_ITEM;
......
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -87,22 +87,23 @@ typedef enum {
typedef enum {
YP_FNONE = 0, /*!< Unspecified. */
YP_FMULTI = 1 << 0, /*!< Multivalued item. */
YP_FUSR1 = 1 << 1, /*!< User-defined flag1. */
YP_FUSR2 = 1 << 2, /*!< User-defined flag2. */
YP_FUSR3 = 1 << 3, /*!< User-defined flag3. */
YP_FUSR4 = 1 << 4, /*!< User-defined flag4. */
YP_FUSR5 = 1 << 5, /*!< User-defined flag5. */
YP_FUSR6 = 1 << 6, /*!< User-defined flag6. */
YP_FUSR7 = 1 << 7, /*!< User-defined flag7. */
YP_FUSR8 = 1 << 8, /*!< User-defined flag8. */
YP_FUSR9 = 1 << 9, /*!< User-defined flag9. */
YP_FUSR10 = 1 << 10, /*!< User-defined flag10. */
YP_FUSR11 = 1 << 11, /*!< User-defined flag11. */
YP_FUSR12 = 1 << 12, /*!< User-defined flag12. */
YP_FUSR13 = 1 << 13, /*!< User-defined flag13. */
YP_FUSR14 = 1 << 14, /*!< User-defined flag14. */
YP_FUSR15 = 1 << 15, /*!< User-defined flag15. */
YP_FUSR16 = 1 << 16, /*!< User-defined flag16. */
YP_FALLOC = 1 << 1, /*!< Allocated item. */
YP_FUSR1 = 1 << 5, /*!< User-defined flag1. */
YP_FUSR2 = 1 << 6, /*!< User-defined flag2. */
YP_FUSR3 = 1 << 7, /*!< User-defined flag3. */
YP_FUSR4 = 1 << 8, /*!< User-defined flag4. */
YP_FUSR5 = 1 << 9, /*!< User-defined flag5. */
YP_FUSR6 = 1 << 10, /*!< User-defined flag6. */
YP_FUSR7 = 1 << 11, /*!< User-defined flag7. */
YP_FUSR8 = 1 << 12, /*!< User-defined flag8. */
YP_FUSR9 = 1 << 13, /*!< User-defined flag9. */
YP_FUSR10 = 1 << 14, /*!< User-defined flag10. */
YP_FUSR11 = 1 << 15, /*!< User-defined flag11. */
YP_FUSR12 = 1 << 16, /*!< User-defined flag12. */
YP_FUSR13 = 1 << 17, /*!< User-defined flag13. */
YP_FUSR14 = 1 << 18, /*!< User-defined flag14. */
YP_FUSR15 = 1 << 19, /*!< User-defined flag15. */
YP_FUSR16 = 1 << 20, /*!< User-defined flag16. */
} yp_flag_t;
/*! Scheme item style. */
......@@ -217,7 +218,7 @@ struct yp_node {
/*! Context parameters for check operations. */
typedef struct {
/*! Used scheme. */
const yp_item_t *scheme;
yp_item_t **scheme;
/*! Index of the current node. */
size_t current;
/*! Node stack. */
......@@ -228,7 +229,7 @@ typedef struct {
* Copies the scheme and reinitializes dynamic parameters.
*
* \param[out] dst New copy of the scheme.
* \param[in] srt Source scheme.
* \param[in] src Source scheme.
*
* \return Error code, KNOT_EOK if success.
*/
......@@ -237,6 +238,30 @@ int yp_scheme_copy(
const yp_item_t *src
);
/*!
* Merges two schemes.
*
* \param[out] dst Merged scheme.
* \param[in] src1 Source scheme1.
* \param[in] src2 Source scheme2.
*
* \return Error code, KNOT_EOK if success.
*/
int yp_scheme_merge(
yp_item_t **dst,
const yp_item_t *src1,
const yp_item_t *src2
);
/*!
* Purges dynamic items from the scheme.
*
* \param[in] scheme Scheme to purge.
*/
void yp_scheme_purge_dynamic(
yp_item_t *scheme
);
/*!
* Deallocates the scheme.
*
......@@ -269,7 +294,7 @@ const yp_item_t* yp_scheme_find(
* \return Context, NULL if error.
*/
yp_check_ctx_t* yp_scheme_check_init(
const yp_item_t *scheme
yp_item_t **scheme
);
/*!
......@@ -319,6 +344,4 @@ void yp_scheme_check_deinit(
yp_check_ctx_t *ctx
);
// TODO: scheme add/remove item.
/*! @} */
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -98,6 +98,40 @@ error_scheme:
yp_scheme_free(scheme);
}
static void scheme_merge_test(void)
{
static const yp_item_t items1[] = {
{ "\x01""1", YP_TSTR, YP_VNONE },
{ "\x01""2", YP_TSTR, YP_VNONE },
{ NULL }
};
static const yp_item_t items2[] = {
{ "\x01""3", YP_TSTR, YP_VNONE },
{ "\x01""4", YP_TSTR, YP_VNONE },
{ NULL }
};
yp_item_t *scheme = NULL;
yp_item_t *tmp = NULL;
int ret = yp_scheme_copy(&tmp, items1);
is_int(KNOT_EOK, ret, "scheme copy");
ret = yp_scheme_merge(&scheme, items1, items2);
is_int(KNOT_EOK, ret, "scheme merge");
yp_scheme_free(tmp);
for (uint8_t i = 0; i < 4; i++) {
yp_name_t name[3] = { '\x01', '1' + i };
const yp_item_t *item = yp_scheme_find(name, NULL, scheme);
ok(item != NULL, "scheme find");
}
yp_scheme_free(scheme);
}
#define SET_INPUT_STR(str) \
ret = yp_set_input_string(yp, str, strlen(str)); \
is_int(KNOT_EOK, ret, "set input string");
......@@ -132,7 +166,7 @@ static void parser_test(void)
goto error_parser;
}
ctx = yp_scheme_check_init(scheme);
ctx = yp_scheme_check_init(&scheme);
ok(ctx != NULL, "create check ctx");
if (ctx == NULL) {
goto error_parser;
......@@ -263,7 +297,7 @@ static void str_test(void)
goto error_str;
}
ctx = yp_scheme_check_init(scheme);
ctx = yp_scheme_check_init(&scheme);
ok(ctx != NULL, "create check ctx");
if (ctx == NULL) {
goto error_str;
......@@ -375,6 +409,7 @@ int main(int argc, char *argv[])
plan_lazy();
scheme_find_test();
scheme_merge_test();
parser_test();
str_test();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment