mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 01:49:35 +00:00
305 lines
9.3 KiB
C
305 lines
9.3 KiB
C
/*
|
|
* Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Internet Systems Consortium, Inc.
|
|
* PO Box 360
|
|
* Newmarket, NH 03857 USA
|
|
* <info@isc.org>
|
|
* http://www.isc.org/
|
|
*/
|
|
|
|
#ifndef DATA_H
|
|
#define DATA_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
/* From FreeBSD sys/queue.h */
|
|
|
|
/*
|
|
* Tail queue declarations.
|
|
*/
|
|
#define TAILQ_HEAD(name, type) \
|
|
struct name { \
|
|
struct type *tqh_first; /* first element */ \
|
|
struct type **tqh_last; /* addr of last next element */ \
|
|
}
|
|
|
|
#define TAILQ_ENTRY(type) \
|
|
struct { \
|
|
struct type *tqe_next; /* next element */ \
|
|
struct type **tqe_prev; /* address of previous next element */ \
|
|
}
|
|
|
|
/*
|
|
* Tail queue functions.
|
|
*/
|
|
#define TAILQ_CONCAT(head1, head2) do { \
|
|
if (!TAILQ_EMPTY(head2)) { \
|
|
*(head1)->tqh_last = (head2)->tqh_first; \
|
|
(head2)->tqh_first->next.tqe_prev = (head1)->tqh_last; \
|
|
(head1)->tqh_last = (head2)->tqh_last; \
|
|
TAILQ_INIT((head2)); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
|
|
|
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
|
|
|
#define TAILQ_FOREACH(var, head) \
|
|
for ((var) = TAILQ_FIRST((head)); \
|
|
(var); \
|
|
(var) = TAILQ_NEXT((var)))
|
|
|
|
#define TAILQ_FOREACH_SAFE(var, head, tvar) \
|
|
for ((var) = TAILQ_FIRST((head)); \
|
|
(var) && ((tvar) = TAILQ_NEXT((var)), 1); \
|
|
(var) = (tvar))
|
|
|
|
#define TAILQ_INIT(head) do { \
|
|
TAILQ_FIRST((head)) = NULL; \
|
|
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
|
} while (0)
|
|
|
|
#define TAILQ_INSERT_AFTER(head, listelm, elm) do { \
|
|
if ((TAILQ_NEXT((elm)) = TAILQ_NEXT((listelm))) != NULL) \
|
|
TAILQ_NEXT((elm))->next.tqe_prev = \
|
|
&TAILQ_NEXT((elm)); \
|
|
else { \
|
|
(head)->tqh_last = &TAILQ_NEXT((elm)); \
|
|
} \
|
|
TAILQ_NEXT((listelm)) = (elm); \
|
|
(elm)->next.tqe_prev = &TAILQ_NEXT((listelm)); \
|
|
} while (0)
|
|
|
|
#define TAILQ_INSERT_BEFORE(listelm, elm) do { \
|
|
(elm)->next.tqe_prev = (listelm)->next.tqe_prev; \
|
|
TAILQ_NEXT((elm)) = (listelm); \
|
|
*(listelm)->next.tqe_prev = (elm); \
|
|
(listelm)->next.tqe_prev = &TAILQ_NEXT((elm)); \
|
|
} while (0)
|
|
|
|
#define TAILQ_INSERT_HEAD(head, elm) do { \
|
|
if ((TAILQ_NEXT((elm)) = TAILQ_FIRST((head))) != NULL) \
|
|
TAILQ_FIRST((head))->next.tqe_prev = \
|
|
&TAILQ_NEXT((elm)); \
|
|
else \
|
|
(head)->tqh_last = &TAILQ_NEXT((elm)); \
|
|
TAILQ_FIRST((head)) = (elm); \
|
|
(elm)->next.tqe_prev = &TAILQ_FIRST((head)); \
|
|
} while (0)
|
|
|
|
#define TAILQ_INSERT_TAIL(head, elm) do { \
|
|
TAILQ_NEXT((elm)) = NULL; \
|
|
(elm)->next.tqe_prev = (head)->tqh_last; \
|
|
*(head)->tqh_last = (elm); \
|
|
(head)->tqh_last = &TAILQ_NEXT((elm)); \
|
|
} while (0)
|
|
|
|
#define TAILQ_LAST(head, headname) \
|
|
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
|
|
|
#define TAILQ_NEXT(elm) ((elm)->next.tqe_next)
|
|
|
|
#define TAILQ_PREV(elm, headname) \
|
|
(*(((struct headname *)((elm)->next.tqe_prev))->tqh_last))
|
|
|
|
#define TAILQ_REMOVE(head, elm) do { \
|
|
if ((TAILQ_NEXT((elm))) != NULL) \
|
|
TAILQ_NEXT((elm))->next.tqe_prev = \
|
|
(elm)->next.tqe_prev; \
|
|
else \
|
|
(head)->tqh_last = (elm)->next.tqe_prev; \
|
|
*(elm)->next.tqe_prev = TAILQ_NEXT((elm)); \
|
|
(elm)->next.tqe_next = (void *)-1; \
|
|
(elm)->next.tqe_prev = (void *)-1; \
|
|
} while (0)
|
|
|
|
#define TAILQ_SWAP(head1, head2, type) do { \
|
|
struct type *swap_first = (head1)->tqh_first; \
|
|
struct type **swap_last = (head1)->tqh_last; \
|
|
(head1)->tqh_first = (head2)->tqh_first; \
|
|
(head1)->tqh_last = (head2)->tqh_last; \
|
|
(head2)->tqh_first = swap_first; \
|
|
(head2)->tqh_last = swap_last; \
|
|
if ((swap_first = (head1)->tqh_first) != NULL) \
|
|
swap_first->next.tqe_prev = &(head1)->tqh_first; \
|
|
else \
|
|
(head1)->tqh_last = &(head1)->tqh_first; \
|
|
if ((swap_first = (head2)->tqh_first) != NULL) \
|
|
swap_first->next.tqe_prev = &(head2)->tqh_first; \
|
|
else \
|
|
(head2)->tqh_last = &(head2)->tqh_first; \
|
|
} while (0)
|
|
|
|
/* From bind9 lib/isc/include/isc/boolean.h */
|
|
|
|
typedef enum { isc_boolean_false = 0, isc_boolean_true = 1 } isc_boolean_t;
|
|
|
|
#define ISC_FALSE isc_boolean_false
|
|
#define ISC_TRUE isc_boolean_true
|
|
#define ISC_TF(x) ((x) ? ISC_TRUE : ISC_FALSE)
|
|
|
|
/* From Kea src/lib/cc/data.h */
|
|
|
|
struct element;
|
|
|
|
/* Element types */
|
|
#define ELEMENT_NONE 0
|
|
#define ELEMENT_INTEGER 1
|
|
#define ELEMENT_REAL 2
|
|
#define ELEMENT_BOOLEAN 3
|
|
#define ELEMENT_NULL 4
|
|
#define ELEMENT_STRING 5
|
|
#define ELEMENT_LIST 6
|
|
#define ELEMENT_MAP 7
|
|
|
|
/* Element string */
|
|
struct string {
|
|
size_t length; /* string length */
|
|
char *content; /* string data */
|
|
};
|
|
|
|
struct string *allocString(void);
|
|
/* In makeString() l == -1 means use strlen(s) */
|
|
struct string *makeString(int l, const char *s);
|
|
/* format ZlLsSbBfXI6 + h */
|
|
struct string *makeStringExt(int l, const char *s, char fmt);
|
|
/* format 6lLIsSbBj */
|
|
struct string *makeStringArray(int l, const char *s, char fmt);
|
|
void appendString(struct string *s, const char *a);
|
|
void concatString(struct string *s, const struct string *a);
|
|
isc_boolean_t eqString(const struct string *s, const struct string *o);
|
|
/* quoting */
|
|
struct string *quote(struct string *);
|
|
|
|
/* Comments */
|
|
struct comment {
|
|
char *line; /* comment line */
|
|
TAILQ_ENTRY(comment) next; /* next line */
|
|
};
|
|
TAILQ_HEAD(comments, comment);
|
|
|
|
struct comment *createComment(const char *line);
|
|
|
|
/* Element list */
|
|
TAILQ_HEAD(list, element);
|
|
|
|
/* Element map */
|
|
TAILQ_HEAD(map, element);
|
|
|
|
/* Element value */
|
|
union value {
|
|
int64_t int_value; /* integer */
|
|
double double_value; /* real */
|
|
isc_boolean_t bool_value; /* boolean */
|
|
/**/ /* null */
|
|
struct string string_value; /* string */
|
|
struct list list_value; /* list */
|
|
struct map map_value; /* map */
|
|
};
|
|
|
|
/* Element */
|
|
struct element {
|
|
int type; /* element type (ELEMENT_XXX) */
|
|
int kind; /* element kind (e.g. ROOT_GROUP) */
|
|
isc_boolean_t skip; /* skip as not converted */
|
|
char *key; /* element key (for map) */
|
|
union value value; /* value */
|
|
struct comments comments; /* associated comments */
|
|
TAILQ_ENTRY(element) next; /* next item in list or map chain */
|
|
};
|
|
|
|
/* Value getters */
|
|
int64_t intValue(const struct element *e);
|
|
double doubleValue(const struct element *e);
|
|
isc_boolean_t boolValue(const struct element *e);
|
|
struct string *stringValue(struct element *e);
|
|
struct list *listValue(struct element *e);
|
|
struct map *mapValue(struct element *e);
|
|
|
|
/* Creators */
|
|
struct element *create(void);
|
|
struct element *createInt(int64_t i);
|
|
struct element *createDouble(double d);
|
|
struct element *createBool(isc_boolean_t b);
|
|
struct element *createNull(void);
|
|
struct element *createString(const struct string *s);
|
|
struct element *createList(void);
|
|
struct element *createMap(void);
|
|
|
|
/* Reset */
|
|
void resetInt(struct element *e, int64_t i);
|
|
void resetDouble(struct element *e, double d);
|
|
void resetBool(struct element *e, isc_boolean_t b);
|
|
void resetNull(struct element *e);
|
|
void resetString(struct element *e, const struct string *s);
|
|
void resetList(struct element *e);
|
|
void resetMap(struct element *e);
|
|
void resetBy(struct element *e, struct element *o);
|
|
|
|
/* List functions */
|
|
struct element *listGet(struct element *l, int i);
|
|
void listSet(struct element *l, struct element *e, int i);
|
|
void listPush(struct element *l, struct element *e);
|
|
void listRemove(struct element *l, int i);
|
|
size_t listSize(const struct element *l);
|
|
void concat(struct element *l, struct element *o);
|
|
|
|
/* Map functions */
|
|
struct element *mapGet(struct element *m, const char *k);
|
|
void mapSet(struct element *m, struct element *e, const char *k);
|
|
void mapRemove(struct element *m, const char *k);
|
|
isc_boolean_t mapContains(const struct element *m, const char *k);
|
|
size_t mapSize(const struct element *m);
|
|
void merge(struct element *m, struct element *o);
|
|
|
|
/* Tools */
|
|
const char *type2name(int t);
|
|
int name2type(const char *n);
|
|
void print(FILE *fp, const struct element *e,
|
|
isc_boolean_t skip, unsigned indent);
|
|
void printList(FILE *fp, const struct list *l,
|
|
isc_boolean_t skip, unsigned indent);
|
|
void printMap(FILE *fp, const struct map *m,
|
|
isc_boolean_t skip, unsigned indent);
|
|
void printString(FILE *fp, const struct string *s);
|
|
isc_boolean_t skip_to_end(const struct element *e);
|
|
|
|
struct element *copy(struct element *e);
|
|
struct element *copyList(struct element *l);
|
|
struct element *copyMap(struct element *m);
|
|
|
|
/* Handles */
|
|
TAILQ_HEAD(handles, handle);
|
|
|
|
struct handle {
|
|
unsigned order; /* order */
|
|
char *key; /* key */
|
|
struct element *value; /* value */
|
|
struct handles values; /* children */
|
|
TAILQ_ENTRY(handle) next; /* siblings */
|
|
};
|
|
|
|
struct handle* mapPop(struct element *);
|
|
void derive(struct handle *, struct handle *);
|
|
|
|
/* Hexadecimal literals */
|
|
struct string *hexaValue(struct element *);
|
|
struct element *createHexa(struct string *);
|
|
|
|
#endif /* DATA_H */
|