Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Icecast-Server
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
spr0cketeer
Icecast-Server
Commits
1d4ce33c
Commit
1d4ce33c
authored
Jul 27, 2018
by
Philipp Schafft
🦁
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ph3-comments'
parents
2f938b85
9cdf5761
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
156 additions
and
1 deletion
+156
-1
src/refobject.h
src/refobject.h
+50
-0
src/reportxml.c
src/reportxml.c
+35
-1
src/reportxml.h
src/reportxml.h
+71
-0
No files found.
src/refobject.h
View file @
1d4ce33c
...
...
@@ -6,6 +6,10 @@
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
/* This file contains the API for the refobject helper type.
* The refobject helper type is a base type that allows building other types with safe reference counting.
*/
#ifndef __REFOBJECT_H__
#define __REFOBJECT_H__
...
...
@@ -18,6 +22,20 @@
#include "icecasttypes.h"
#include "compat.h"
/* The following macros are defined. The definition depends on if the compiler
* supports transparent unions. If supported full type checking is enabled.
* If the compiler does not support transparent unions, we fall back to using
* (void*) pointers.
*
* REFOBJECT_NULL
* Can be used to set an refobject to NULL.
* REFOBJECT_IS_NULL(x)
* Can be used to check if the refobject x is NULL.
* Checking by doing (x == NULL) does not work with transparent unions
* as the operation is only defined for it's members.
* REFOBJECT_TO_TYPE(type,x)
* This casts the refobject (x) to the type (type).
*/
#ifdef HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION
#define REFOBJECT_NULL ((refobject_t)(refobject_base_t*)NULL)
#define REFOBJECT_IS_NULL(x) (((refobject_t)(x)).refobject_base == NULL)
...
...
@@ -28,8 +46,19 @@
#define REFOBJECT_TO_TYPE(x,y) ((y)(x))
#endif
/* Type used for callback called then the object is actually freed
* That is once all references to it are gone.
*
* If the callback does not set *userdata to NULL *userdata will
* be freed automatically by calling free(3).
*
* This function must not try to deallocate or alter self.
*/
typedef
void
(
*
refobject_free_t
)(
refobject_t
self
,
void
**
userdata
);
/* Only defined here as the size must be publically known.
* DO NOT use any of the members in here directly!
*/
struct
refobject_base_tag
{
size_t
refc
;
mutex_t
lock
;
...
...
@@ -39,12 +68,33 @@ struct refobject_base_tag {
refobject_t
associated
;
};
/* Create a new refobject
* The total length of the new object is given by len (see malloc(3)),
* the callback called on free is given by freecb (see refobject_free_t above),
* the userdata us given by userdata,
* the name for the object is given by name, and
* the associated refobject is given by associated.
*
* All parameters beside len are optional and can be NULL/REFOBJECT_NULL.
* If no freecb is given the userdata is freed (see refobject_free_t above).
*/
refobject_t
refobject_new
(
size_t
len
,
refobject_free_t
freecb
,
void
*
userdata
,
const
char
*
name
,
refobject_t
associated
);
/* This increases the reference counter of the object */
int
refobject_ref
(
refobject_t
self
);
/* This decreases the reference counter of the object.
* If the object's reference counter reaches zero the object is freed.
*/
int
refobject_unref
(
refobject_t
self
);
/* This gets and sets the userdata */
void
*
refobject_get_userdata
(
refobject_t
self
);
int
refobject_set_userdata
(
refobject_t
self
,
void
*
userdata
);
/* This gets the object's name */
const
char
*
refobject_get_name
(
refobject_t
self
);
/* This gets the object's associated object. */
refobject_t
refobject_get_associated
(
refobject_t
self
);
#endif
src/reportxml.c
View file @
1d4ce33c
...
...
@@ -28,57 +28,90 @@
#include "logging.h"
#define CATMODULE "reportxml"
/* The report XML document type */
struct
reportxml_tag
{
/* base object */
refobject_base_t
__base
;
/* the root report XML node of the document */
reportxml_node_t
*
root
;
};
/* The report XML node type */
struct
reportxml_node_tag
{
/* base object */
refobject_base_t
__base
;
/* an XML node used to store the attributes */
xmlNodePtr
xmlnode
;
/* the type of the node */
reportxml_node_type_t
type
;
/* the report XML childs */
reportxml_node_t
**
childs
;
size_t
childs_len
;
/* the XML childs (used by <extension>) */
xmlNodePtr
*
xml_childs
;
size_t
xml_childs_len
;
/* the node's text content (used by <text>) */
char
*
content
;
};
/* The report XML database type */
struct
reportxml_database_tag
{
/* base object */
refobject_base_t
__base
;
/* the lock used to ensure the database object is thread safe. */
mutex_t
lock
;
/* The tree of definitions */
avl_tree
*
definitions
;
};
/* The nodeattr structure is used to store definition of node attributes */
struct
nodeattr
;
struct
nodeattr
{
/* name of the attribute */
const
char
*
name
;
/* the type of the attribute. This is based on the DTD */
const
char
*
type
;
/* the default value for the attribute if any */
const
char
*
def
;
/* whether the attribute is required or not */
int
required
;
/* a function that can be used to check the content of the attribute if any */
int
(
*
checker
)(
const
struct
nodeattr
*
attr
,
const
char
*
str
);
/* NULL terminated list of possible values (if enum) */
const
char
*
values
[
32
];
};
/* The type of the content an node has */
enum
nodecontent
{
/* The node may not have any content */
NC_NONE
,
/* The node may have children */
NC_CHILDS
,
/* The node may have a text content */
NC_CONTENT
,
/* The node may have XML children */
NC_XML
};
/* This structure is used to define a node */
struct
nodedef
{
/* the type of the node */
reportxml_node_type_t
type
;
/* the name of the corresponding XML node */
const
char
*
name
;
/* The type of the content the node may have */
enum
nodecontent
content
;
/* __attr__eol terminated list of attributes the node may have */
const
struct
nodeattr
*
attr
[
12
];
/* REPORTXML_NODE_TYPE__ERROR terminated list of child node types the node may have */
const
reportxml_node_type_t
childs
[
12
];
};
/* Prototypes */
static
int
__attach_copy_of_node_or_definition
(
reportxml_node_t
*
parent
,
reportxml_node_t
*
node
,
reportxml_database_t
*
db
,
ssize_t
depth
);
static
reportxml_node_t
*
__reportxml_database_build_node_ext
(
reportxml_database_t
*
db
,
const
char
*
id
,
ssize_t
depth
,
reportxml_node_type_t
*
acst_type_ret
);
/* definition of known attributes */
static
const
struct
nodeattr
__attr__eol
[
1
]
=
{{
NULL
,
NULL
,
NULL
,
0
,
NULL
,
{
NULL
}}};
static
const
struct
nodeattr
__attr_version
[
1
]
=
{{
"version"
,
"CDATA"
,
"0.0.1"
,
1
,
NULL
,
{
"0.0.1"
,
NULL
}}};
static
const
struct
nodeattr
__attr_xmlns
[
1
]
=
{{
"xmlns"
,
"URI"
,
"http://icecast.org/specs/reportxml-0.0.1"
,
1
,
NULL
,
{
"http://icecast.org/specs/reportxml-0.0.1"
,
NULL
}}};
...
...
@@ -108,6 +141,7 @@ static const struct nodeattr __attr__resource_type[1] = {{"type", NULL
static
const
struct
nodeattr
__attr__value_type
[
1
]
=
{{
"type"
,
NULL
,
NULL
,
1
,
NULL
,
{
"null"
,
"int"
,
"float"
,
"uuid"
,
"string"
,
"structure"
,
"uri"
,
"pointer"
,
"version"
,
"protocol"
,
"username"
,
"password"
,
NULL
}}};
static
const
struct
nodeattr
__attr__reference_type
[
1
]
=
{{
"type"
,
NULL
,
NULL
,
1
,
NULL
,
{
"documentation"
,
"log"
,
"report"
,
"related"
,
NULL
}}};
/* definition of known nodes */
/* Helper:
* grep '^ *REPORTXML_NODE_TYPE_' reportxml.h | sed 's/^\( *REPORTXML_NODE_TYPE_\([^,]*\)\),*$/\1 \2/;' | while read l s; do c=$(tr A-Z a-z <<<"$s"); printf " {%-32s \"%-16s 0, {__attr__eol}},\n" "$l," "$c\","; done
*/
...
...
src/reportxml.h
View file @
1d4ce33c
...
...
@@ -6,6 +6,8 @@
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
/* This file contains the API for report XML document parsing, manipulation, and rendering. */
#ifndef __REPORTXML_H__
#define __REPORTXML_H__
...
...
@@ -14,52 +16,121 @@
#include "icecasttypes.h"
#include "compat.h"
/* XML Tag Types
* While a hint of what the nodes are used for is given, see the specification for more details.
*/
typedef
enum
{
/* This is a virtual type used to indicate error conditions */
REPORTXML_NODE_TYPE__ERROR
,
/* <report> is the root element of report XML documents */
REPORTXML_NODE_TYPE_REPORT
,
/* <definition> is used to define templates */
REPORTXML_NODE_TYPE_DEFINITION
,
/* <incident> defines an event that is reported */
REPORTXML_NODE_TYPE_INCIDENT
,
/* <state> defines the state an <incident> resulted in */
REPORTXML_NODE_TYPE_STATE
,
/* <backtrace> provides helpful information about the location some event happend */
REPORTXML_NODE_TYPE_BACKTRACE
,
/* <position> defines an element within <backtrace> */
REPORTXML_NODE_TYPE_POSITION
,
/* <more> allows to skip <position>s in <backtrace> for any reason
* (e.g. they are unknown or consider of no intrest)
*/
REPORTXML_NODE_TYPE_MORE
,
/* <fix> provides a machine readable way to actually fix the problem */
REPORTXML_NODE_TYPE_FIX
,
/* <action> defines a specific action to do */
REPORTXML_NODE_TYPE_ACTION
,
/* <reason> allows to define why an event happend */
REPORTXML_NODE_TYPE_REASON
,
/* <text> is used to provide messages to the user.
* The content of <text> is not machine readable.
*/
REPORTXML_NODE_TYPE_TEXT
,
/* <timestamp> provides a way to present a point in time an event happend */
REPORTXML_NODE_TYPE_TIMESTAMP
,
/* <resource> names a resource that was involved in the event such as user input or the result */
REPORTXML_NODE_TYPE_RESOURCE
,
/* <value> provides an actual value for a <resource> */
REPORTXML_NODE_TYPE_VALUE
,
/* <reference> provides a way to refer to external documents such as documentation */
REPORTXML_NODE_TYPE_REFERENCE
,
/* <extension> is used to allow application specific extensions */
REPORTXML_NODE_TYPE_EXTENSION
}
reportxml_node_type_t
;
/* ---[ Document level ]--- */
/* The document object is NOT thread safe. */
/* This creates a new, empty report XML document */
reportxml_t
*
reportxml_new
(
void
);
/* This gets the root node of a report XML document */
reportxml_node_t
*
reportxml_get_root_node
(
reportxml_t
*
report
);
/* This selects a node by an attribute and it's value.
* This is mostly useful to look for an object by using it's ID.
* If more than one node matches the first one found is returned.
* If the parameter include_definitions is true nodes from within
* <definition> are also considered. If it is false nodes inside
* <definition>s are skipped.
*/
reportxml_node_t
*
reportxml_get_node_by_attribute
(
reportxml_t
*
report
,
const
char
*
key
,
const
char
*
value
,
int
include_definitions
);
/* This function parses an XML document and returns the parst report XML document */
reportxml_t
*
reportxml_parse_xmldoc
(
xmlDocPtr
doc
);
/* This function renders an report XML document as XML structure */
xmlDocPtr
reportxml_render_xmldoc
(
reportxml_t
*
report
);
/* ---[ Node level ]--- */
/* The node object is NOT thread safe. */
/* This creates a new node of type type.
* It's id, definition, and akindof attributes can be given as parameters.
*/
reportxml_node_t
*
reportxml_node_new
(
reportxml_node_type_t
type
,
const
char
*
id
,
const
char
*
definition
,
const
char
*
akindof
);
/* This parses an XML node and returns the resulting report XML node */
reportxml_node_t
*
reportxml_node_parse_xmlnode
(
xmlNodePtr
xmlnode
);
/* Copy an report XML node (and it's children) */
reportxml_node_t
*
reportxml_node_copy
(
reportxml_node_t
*
node
);
/* Renders an report XML node as XML node */
xmlNodePtr
reportxml_node_render_xmlnode
(
reportxml_node_t
*
node
);
/* This gets the type of an report XML node */
reportxml_node_type_t
reportxml_node_get_type
(
reportxml_node_t
*
node
);
/* Gets and Sets attribute values */
int
reportxml_node_set_attribute
(
reportxml_node_t
*
node
,
const
char
*
key
,
const
char
*
value
);
char
*
reportxml_node_get_attribute
(
reportxml_node_t
*
node
,
const
char
*
key
);
/* Adds, counts, and get child nodes */
int
reportxml_node_add_child
(
reportxml_node_t
*
node
,
reportxml_node_t
*
child
);
ssize_t
reportxml_node_count_child
(
reportxml_node_t
*
node
);
reportxml_node_t
*
reportxml_node_get_child
(
reportxml_node_t
*
node
,
size_t
idx
);
/* This gets an child by it's value of the given attribute. See reportxml_get_node_by_attribute() for more details. */
reportxml_node_t
*
reportxml_node_get_child_by_attribute
(
reportxml_node_t
*
node
,
const
char
*
key
,
const
char
*
value
,
int
include_definitions
);
/* This gets and sets the text content of an node (used for <text>) */
int
reportxml_node_set_content
(
reportxml_node_t
*
node
,
const
char
*
value
);
char
*
reportxml_node_get_content
(
reportxml_node_t
*
node
);
/* Adds, counts, and gets XML childs (used for <extension>) */
int
reportxml_node_add_xml_child
(
reportxml_node_t
*
node
,
xmlNodePtr
child
);
ssize_t
reportxml_node_count_xml_child
(
reportxml_node_t
*
node
);
xmlNodePtr
reportxml_node_get_xml_child
(
reportxml_node_t
*
node
,
size_t
idx
);
/* ---[ Database level ]--- */
/* The database object is thread safe. */
/* Create a new database object */
reportxml_database_t
*
reportxml_database_new
(
void
);
/* Add an report to the database */
int
reportxml_database_add_report
(
reportxml_database_t
*
db
,
reportxml_t
*
report
);
/* Build a node (copy) from the data in the database based on the given ID (using "definition" and "defines" attributes)
* depth may be used to select how many recursions may be used to resolve definitions within defines.
* The default value is selected by passing -1 (recommended).
*/
reportxml_node_t
*
reportxml_database_build_node
(
reportxml_database_t
*
db
,
const
char
*
id
,
ssize_t
depth
);
/* This does the same as reportxml_database_build_node() except that a new report document is returned. */
reportxml_t
*
reportxml_database_build_report
(
reportxml_database_t
*
db
,
const
char
*
id
,
ssize_t
depth
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment